merge tutor updates #82
|
@ -70,3 +70,36 @@ services:
|
||||||
- "traefik.http.routers.app.tls=true"
|
- "traefik.http.routers.app.tls=true"
|
||||||
- "traefik.http.routers.app.entryPoints=web,websecure"
|
- "traefik.http.routers.app.entryPoints=web,websecure"
|
||||||
- "traefik.http.routers.app.tls.certresolver=le"
|
- "traefik.http.routers.app.tls.certresolver=le"
|
||||||
|
|
||||||
|
mongodb:
|
||||||
|
image: mongo
|
||||||
|
container_name: mongodb
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: root
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: 8nP7s0a # Can not be changed again later on
|
||||||
|
volumes:
|
||||||
|
- database:/data/db
|
||||||
|
|
||||||
|
dbadmin:
|
||||||
|
image: mongo-express
|
||||||
|
container_name: dbadmin
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
ME_CONFIG_BASICAUTH_USERNAME: student # Access to web interface: username
|
||||||
|
ME_CONFIG_BASICAUTH_PASSWORD: studious # Access to web interface: password
|
||||||
|
ME_CONFIG_MONGODB_ADMINUSERNAME: root
|
||||||
|
ME_CONFIG_MONGODB_ADMINPASSWORD: 8nP7s0a # must correspond to the db
|
||||||
|
ME_CONFIG_MONGODB_PORT: 27017 # Default 27017
|
||||||
|
ME_CONFIG_MONGODB_SERVER: mongodb
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.dbadmin.rule=Host(`dbadmin1.${PUB_IP}.nip.io`)"
|
||||||
|
- "traefik.http.routers.dbadmin.service=dbadmin"
|
||||||
|
- "traefik.http.services.dbadmin.loadbalancer.server.port=8081"
|
||||||
|
- "traefik.http.routers.dbadmin.tls=true"
|
||||||
|
- "traefik.http.routers.dbadmin.entryPoints=web,websecure"
|
||||||
|
- "traefik.http.routers.dbadmin.tls.certresolver=le"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
database:
|
||||||
|
|
|
@ -27,6 +27,15 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
|
<version>3.2.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
package ch.unisg.tapastasks;
|
package ch.unisg.tapastasks;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.adapter.out.persistence.mongodb.TaskRepository;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
|
@EnableMongoRepositories(basePackageClasses = TaskRepository.class)
|
||||||
public class TapasTasksApplication {
|
public class TapasTasksApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication tapasTasksApp = new SpringApplication(TapasTasksApplication.class);
|
SpringApplication tapasTasksApp = new SpringApplication(TapasTasksApplication.class);
|
||||||
tapasTasksApp.run(args);
|
tapasTasksApp.run(args);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.adapter.out.persistence.mongodb;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Document(collection = "tasks")
|
||||||
|
public class MongoTaskDocument {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public String taskId;
|
||||||
|
|
||||||
|
public String taskName;
|
||||||
|
public String taskType;
|
||||||
|
public String originalTaskUri;
|
||||||
|
public String taskStatus;
|
||||||
|
public String taskListName;
|
||||||
|
|
||||||
|
|
||||||
|
public MongoTaskDocument(String taskId, String taskName, String taskType,
|
||||||
|
String originalTaskUri,
|
||||||
|
String taskStatus, String taskListName) {
|
||||||
|
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.taskName = taskName;
|
||||||
|
this.taskType = taskType;
|
||||||
|
this.originalTaskUri = originalTaskUri;
|
||||||
|
this.taskStatus = taskStatus;
|
||||||
|
this.taskListName = taskListName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.adapter.out.persistence.mongodb;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class TaskMapper {
|
||||||
|
|
||||||
|
Task mapToDomainEntity(MongoTaskDocument task) {
|
||||||
|
return Task.withIdNameTypeOriginaluriStatus(
|
||||||
|
new Task.TaskId(task.taskId),
|
||||||
|
new Task.TaskName(task.taskName),
|
||||||
|
new Task.TaskType(task.taskType),
|
||||||
|
new Task.OriginalTaskUri(task.originalTaskUri),
|
||||||
|
new Task.TaskStatus(Task.Status.valueOf(task.taskStatus))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MongoTaskDocument mapToMongoDocument(Task task) {
|
||||||
|
return new MongoTaskDocument(
|
||||||
|
task.getTaskId().getValue(),
|
||||||
|
task.getTaskName().getValue(),
|
||||||
|
task.getTaskType().getValue(),
|
||||||
|
task.getOriginalTaskUri().getValue(),
|
||||||
|
task.getTaskStatus().getValue().toString(),
|
||||||
|
TaskList.getTapasTaskList().getTaskListName().getValue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.adapter.out.persistence.mongodb;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.AddTaskPort;
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.LoadTaskPort;
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TaskPersistenceAdapter implements
|
||||||
|
AddTaskPort,
|
||||||
|
LoadTaskPort {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final TaskRepository taskRepository;
|
||||||
|
|
||||||
|
private final TaskMapper taskMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTask(Task task) {
|
||||||
|
MongoTaskDocument mongoTaskDocument = taskMapper.mapToMongoDocument(task);
|
||||||
|
taskRepository.save(mongoTaskDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.adapter.out.persistence.mongodb;
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TaskRepository extends MongoRepository<MongoTaskDocument,String> {
|
||||||
|
|
||||||
|
public MongoTaskDocument findByTaskId(String taskId, String taskListName);
|
||||||
|
|
||||||
|
public List<MongoTaskDocument> findByTaskListName(String taskListName);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.application.port.out;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
|
|
||||||
|
public interface AddTaskPort {
|
||||||
|
|
||||||
|
void addTask(Task task);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.application.port.out;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
|
|
||||||
|
public interface LoadTaskPort {
|
||||||
|
|
||||||
|
Task loadTask(Task.TaskId taskId, TaskList.TaskListName taskListName);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.application.port.out;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
|
|
||||||
|
public interface TaskListLock {
|
||||||
|
|
||||||
|
void lockTaskList(TaskList.TaskListName taskListName);
|
||||||
|
|
||||||
|
void releaseTaskList(TaskList.TaskListName taskListName);
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,9 @@ package ch.unisg.tapastasks.tasks.application.service;
|
||||||
|
|
||||||
import ch.unisg.tapastasks.tasks.application.port.in.AddNewTaskToTaskListCommand;
|
import ch.unisg.tapastasks.tasks.application.port.in.AddNewTaskToTaskListCommand;
|
||||||
import ch.unisg.tapastasks.tasks.application.port.in.AddNewTaskToTaskListUseCase;
|
import ch.unisg.tapastasks.tasks.application.port.in.AddNewTaskToTaskListUseCase;
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.AddTaskPort;
|
||||||
import ch.unisg.tapastasks.tasks.application.port.out.NewTaskAddedEventPort;
|
import ch.unisg.tapastasks.tasks.application.port.out.NewTaskAddedEventPort;
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.TaskListLock;
|
||||||
import ch.unisg.tapastasks.tasks.domain.Task;
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
|
|
||||||
import ch.unisg.tapastasks.tasks.domain.NewTaskAddedEvent;
|
import ch.unisg.tapastasks.tasks.domain.NewTaskAddedEvent;
|
||||||
|
@ -17,11 +19,14 @@ import javax.transaction.Transactional;
|
||||||
public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase {
|
public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase {
|
||||||
|
|
||||||
private final NewTaskAddedEventPort newTaskAddedEventPort;
|
private final NewTaskAddedEventPort newTaskAddedEventPort;
|
||||||
|
private final AddTaskPort addTaskToRepositoryPort;
|
||||||
|
private final TaskListLock taskListLock;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task addNewTaskToTaskList(AddNewTaskToTaskListCommand command) {
|
public Task addNewTaskToTaskList(AddNewTaskToTaskListCommand command) {
|
||||||
TaskList taskList = TaskList.getTapasTaskList();
|
TaskList taskList = TaskList.getTapasTaskList();
|
||||||
|
|
||||||
|
taskListLock.lockTaskList(taskList.getTaskListName());
|
||||||
Task newTask = (command.getOriginalTaskUri().isPresent()) ?
|
Task newTask = (command.getOriginalTaskUri().isPresent()) ?
|
||||||
// Create a delegated task that points back to the original task
|
// Create a delegated task that points back to the original task
|
||||||
taskList.addNewTaskWithNameAndTypeAndOriginalTaskUri(command.getTaskName(),
|
taskList.addNewTaskWithNameAndTypeAndOriginalTaskUri(command.getTaskName(),
|
||||||
|
@ -29,6 +34,9 @@ public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase
|
||||||
// Create an original task
|
// Create an original task
|
||||||
: taskList.addNewTaskWithNameAndType(command.getTaskName(), command.getTaskType());
|
: taskList.addNewTaskWithNameAndType(command.getTaskName(), command.getTaskType());
|
||||||
|
|
||||||
|
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.
|
//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.
|
//This event should be considered as a light-weight "integration event" to communicate with other services.
|
||||||
//Domain events are usually rather "fat". In our implementation we simplify at this point. In general, it is
|
//Domain events are usually rather "fat". In our implementation we simplify at this point. In general, it is
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ch.unisg.tapastasks.tasks.application.service;
|
||||||
|
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.TaskListLock;
|
||||||
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NoOpTaskListLock implements TaskListLock {
|
||||||
|
@Override
|
||||||
|
public void lockTaskList(TaskList.TaskListName taskListName) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseTaskList(TaskList.TaskListName taskListName) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package ch.unisg.tapastasks.tasks.application.service;
|
||||||
|
|
||||||
import ch.unisg.tapastasks.tasks.application.port.in.RetrieveTaskFromTaskListQuery;
|
import ch.unisg.tapastasks.tasks.application.port.in.RetrieveTaskFromTaskListQuery;
|
||||||
import ch.unisg.tapastasks.tasks.application.port.in.RetrieveTaskFromTaskListUseCase;
|
import ch.unisg.tapastasks.tasks.application.port.in.RetrieveTaskFromTaskListUseCase;
|
||||||
|
import ch.unisg.tapastasks.tasks.application.port.out.LoadTaskPort;
|
||||||
import ch.unisg.tapastasks.tasks.domain.Task;
|
import ch.unisg.tapastasks.tasks.domain.Task;
|
||||||
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
import ch.unisg.tapastasks.tasks.domain.TaskList;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
@ -14,9 +15,17 @@ import java.util.Optional;
|
||||||
@Component
|
@Component
|
||||||
@Transactional
|
@Transactional
|
||||||
public class RetrieveTaskFromTaskListService implements RetrieveTaskFromTaskListUseCase {
|
public class RetrieveTaskFromTaskListService implements RetrieveTaskFromTaskListUseCase {
|
||||||
|
|
||||||
|
private final LoadTaskPort loadTaskFromRepositoryPort;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Task> retrieveTaskFromTaskList(RetrieveTaskFromTaskListQuery query) {
|
public Optional<Task> retrieveTaskFromTaskList(RetrieveTaskFromTaskListQuery query) {
|
||||||
TaskList taskList = TaskList.getTapasTaskList();
|
TaskList taskList = TaskList.getTapasTaskList();
|
||||||
return taskList.retrieveTaskById(query.getTaskId());
|
|
||||||
|
Optional<Task> task = taskList.retrieveTaskById(query.getTaskId());
|
||||||
|
|
||||||
|
Optional<Task> taskFromRepo = Optional.ofNullable(loadTaskFromRepositoryPort.loadTask(query.getTaskId(), taskList.getTaskListName()));
|
||||||
|
|
||||||
|
return taskFromRepo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,17 +49,39 @@ public class Task {
|
||||||
this.outputData = null;
|
this.outputData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Task createTaskWithNameAndType(TaskName name, TaskType type) {
|
//Constructor from repo
|
||||||
|
public Task(TaskId taskId, TaskName taskName, TaskType taskType, OriginalTaskUri taskUri,
|
||||||
|
TaskStatus taskStatus) {
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.taskName = taskName;
|
||||||
|
this.taskType = taskType;
|
||||||
|
this.originalTaskUri = taskUri;
|
||||||
|
this.taskStatus = taskStatus;
|
||||||
|
this.inputData = null;
|
||||||
|
this.outputData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Task createTaskWithNameAndType(TaskName name, TaskType type) {
|
||||||
//This is a simple debug message to see that the request has reached the right method in the core
|
//This is a simple debug message to see that the request has reached the right method in the core
|
||||||
System.out.println("New Task: " + name.getValue() + " " + type.getValue());
|
System.out.println("New Task: " + name.getValue() + " " + type.getValue());
|
||||||
return new Task(name, type, null);
|
return new Task(name, type, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Task createTaskWithNameAndTypeAndOriginalTaskUri(TaskName name, TaskType type,
|
public static Task createTaskWithNameAndTypeAndOriginalTaskUri(TaskName name, TaskType type,
|
||||||
OriginalTaskUri originalTaskUri) {
|
OriginalTaskUri originalTaskUri) {
|
||||||
return new Task(name, type, originalTaskUri);
|
return new Task(name, type, originalTaskUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This is for recreating a task from a repository.
|
||||||
|
public static Task withIdNameTypeOriginaluriStatus(TaskId taskId, TaskName taskName,
|
||||||
|
TaskType taskType,
|
||||||
|
OriginalTaskUri originalTaskUri,
|
||||||
|
TaskStatus taskStatus) {
|
||||||
|
return new Task(taskId, taskName, taskType, originalTaskUri, taskStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public static class TaskId {
|
public static class TaskId {
|
||||||
String value;
|
String value;
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
server.port=8081
|
server.port=8081
|
||||||
|
//spring.data.mongodb.uri=mongodb://127.0.0.1:27017
|
||||||
|
spring.data.mongodb.uri=mongodb://root:8nP7s0a@mongodb:27017/
|
||||||
|
spring.data.mongodb.database=tapas-tasks
|
||||||
baseuri=https://tapas-tasks.86-119-34-23.nip.io/
|
baseuri=https://tapas-tasks.86-119-34-23.nip.io/
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user