Merging dev to main #107

Merged
Maece97 merged 52 commits from dev into main 2021-12-23 16:12:19 +00:00
43 changed files with 216 additions and 261 deletions
Showing only changes of commit 6bb206ccdb - Show all commits

View File

@ -9,7 +9,7 @@ import java.util.Set;
public abstract class SelfValidating<T> { public abstract class SelfValidating<T> {
private Validator validator; private final Validator validator;
protected SelfValidating() { protected SelfValidating() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

View File

@ -6,7 +6,7 @@ import lombok.Setter;
public class Task { public class Task {
@Getter @Getter
private String taskID; private final String taskID;
@Getter @Getter
@Setter @Setter
@ -15,7 +15,7 @@ public class Task {
// TODO maybe create a value object for inputData so we can make sure it is in the right // TODO maybe create a value object for inputData so we can make sure it is in the right
// format. // format.
@Getter @Getter
private String inputData; private final String inputData;
public Task(String taskID, String inputData) { public Task(String taskID, String inputData) {
this.taskID = taskID; this.taskID = taskID;

View File

@ -9,7 +9,7 @@ import ch.unisg.executorbase.Task;
public abstract class ExecuteTaskServiceBase implements ExecuteTaskServiceInterface { public abstract class ExecuteTaskServiceBase implements ExecuteTaskServiceInterface {
private Logger logger = Logger.getLogger(ExecuteTaskServiceBase.class.getName()); private final Logger logger = Logger.getLogger(ExecuteTaskServiceBase.class.getName());
@Autowired @Autowired
private Executor executor; private Executor executor;

View File

@ -18,7 +18,7 @@ public class ExecutionFinishedService {
@Value("${roster.uri}") @Value("${roster.uri}")
private String rosterUri; private String rosterUri;
private Logger logger = Logger.getLogger(ExecutionFinishedService.class.getName()); private final Logger logger = Logger.getLogger(ExecutionFinishedService.class.getName());
/** /**
* Publishes the execution finished event * Publishes the execution finished event

View File

@ -9,7 +9,7 @@ import java.util.Set;
public class SelfValidating<T> { public class SelfValidating<T> {
private Validator validator; private final Validator validator;
public SelfValidating() { public SelfValidating() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

View File

@ -8,10 +8,10 @@ import org.springframework.stereotype.Repository;
@Repository @Repository
public interface ExecutorRepository extends MongoRepository<MongoExecutorDocument, String> { public interface ExecutorRepository extends MongoRepository<MongoExecutorDocument, String> {
public MongoExecutorDocument findByExecutorUri(String executorUri, String executorTaskType); MongoExecutorDocument findByExecutorUri(String executorUri, String executorTaskType);
public List<MongoExecutorDocument> findByExecutorTaskType(String executorTaskType); List<MongoExecutorDocument> findByExecutorTaskType(String executorTaskType);
public void deleteByExecutorUri(String executorUri); void deleteByExecutorUri(String executorUri);
} }

View File

@ -4,7 +4,7 @@ import lombok.Getter;
public class ExecutorAddedEvent { public class ExecutorAddedEvent {
@Getter @Getter
private ExecutorClass executorClass; private final ExecutorClass executorClass;
public ExecutorAddedEvent(ExecutorClass executorClass) { this.executorClass = executorClass; } public ExecutorAddedEvent(ExecutorClass executorClass) { this.executorClass = executorClass; }
} }

View File

@ -4,7 +4,7 @@ import lombok.Getter;
public class ExecutorRemovedEvent { public class ExecutorRemovedEvent {
@Getter @Getter
private ExecutorClass executorClass; private final ExecutorClass executorClass;
public ExecutorRemovedEvent(ExecutorClass executorClass) { this.executorClass = executorClass; } public ExecutorRemovedEvent(ExecutorClass executorClass) { this.executorClass = executorClass; }
} }

View File

@ -1,4 +1,4 @@
package ch.unisg.executorpool; package ch.unisg.executorpool.executorpool;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -32,9 +32,9 @@ public class AddNewExecutorToExecutorPoolSystemTest {
ExecutorTaskType executorTaskType = new ExecutorTaskType("system-integration-test-type"); ExecutorTaskType executorTaskType = new ExecutorTaskType("system-integration-test-type");
ExecutorUri executorUri = new ExecutorUri(java.net.URI.create("example.org")); ExecutorUri executorUri = new ExecutorUri(java.net.URI.create("example.org"));
ResponseEntity<String> response = whenAddNewExecutorToEmptyPool(executorTaskType, executorUri); ResponseEntity response = whenAddNewExecutorToEmptyPool(executorTaskType, executorUri);
JSONObject responseJson = new JSONObject(response.getBody().toString()); var responseJson = new JSONObject(response.getBody().toString());
String respExecutorUri = responseJson.getString("executorUri"); String respExecutorUri = responseJson.getString("executorUri");
String respExecutorTaskType = responseJson.getString("executorTaskType"); String respExecutorTaskType = responseJson.getString("executorTaskType");
@ -59,7 +59,7 @@ public class AddNewExecutorToExecutorPoolSystemTest {
HttpEntity<String> request = new HttpEntity<>(jsonPayLoad,headers); HttpEntity<String> request = new HttpEntity<>(jsonPayLoad,headers);
return restTemplate.exchange("/executor-pool/AddExecutor", HttpMethod.POST, request, Object.class); return restTemplate.exchange("/executor-pool/executors", HttpMethod.POST, request, Object.class);
} }

View File

@ -1,4 +1,4 @@
package ch.unisg.executorpool; package ch.unisg.executorpool.executorpool.adapter.in.web;
import ch.unisg.executorpool.application.port.out.LoadExecutorPort; import ch.unisg.executorpool.application.port.out.LoadExecutorPort;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -56,7 +56,7 @@ public class AddNewExecutorToExecutorPoolWebControllerTest {
.addNewExecutorToExecutorPool(addNewExecutorToExecutorPoolCommand)) .addNewExecutorToExecutorPool(addNewExecutorToExecutorPoolCommand))
.thenReturn(executorStub); .thenReturn(executorStub);
mockMvc.perform(post("/executor-pool/AddExecutor") mockMvc.perform(post("/executor-pool/executors")
.contentType(ExecutorJsonRepresentation.EXECUTOR_MEDIA_TYPE) .contentType(ExecutorJsonRepresentation.EXECUTOR_MEDIA_TYPE)
.content(jsonPayLoad)) .content(jsonPayLoad))
.andExpect(status().isCreated()); .andExpect(status().isCreated());

View File

@ -1,4 +1,4 @@
package ch.unisg.executorpool; package ch.unisg.executorpool.executorpool.application.service;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;

View File

@ -1,4 +1,4 @@
package ch.unisg.executorpool; package ch.unisg.executorpool.executorpool.domain;
import java.net.URI; import java.net.URI;
@ -13,8 +13,6 @@ import ch.unisg.executorpool.domain.ExecutorClass.ExecutorTaskType;
public class ExecutorPoolTest { public class ExecutorPoolTest {
private static final URI URI = null;
@Test @Test
void addNewExecutorToExecutorPoolSuccess() { void addNewExecutorToExecutorPoolSuccess() {
ExecutorPool executorPool = ExecutorPool.getExecutorPool(); ExecutorPool executorPool = ExecutorPool.getExecutorPool();

View File

@ -29,7 +29,7 @@ public class ApplyForTaskWebController {
**/ **/
@PostMapping(path = "/task/apply", consumes = {"application/json"}) @PostMapping(path = "/task/apply", consumes = {"application/json"})
public Task applyForTask (@RequestBody ExecutorInfo executorInfo) { public Task applyForTask (@RequestBody ExecutorInfo executorInfo) {
logger.info("Roster | Execuor applying for task"); logger.info("Roster | Executor applying for task");
ApplyForTaskCommand command = new ApplyForTaskCommand(executorInfo.getExecutorType(), ApplyForTaskCommand command = new ApplyForTaskCommand(executorInfo.getExecutorType(),
executorInfo.getExecutorURI()); executorInfo.getExecutorURI());

View File

@ -5,5 +5,5 @@ import org.springframework.stereotype.Repository;
@Repository @Repository
public interface RosterRepository extends MongoRepository<MongoRosterDocument,String>{ public interface RosterRepository extends MongoRepository<MongoRosterDocument,String>{
public MongoRosterDocument findByTaskId(String taskId); MongoRosterDocument findByTaskId(String taskId);
} }

View File

@ -12,10 +12,10 @@ public class Roster {
private static final Roster roster = new Roster(); private static final Roster roster = new Roster();
// Queues which hold all the tasks which need to be assigned | Will be replaced by message queue later // Queues which hold all the tasks which need to be assigned | Will be replaced by message queue later
private HashMap<String, ArrayList<Task>> queues = new HashMap<>(); private final HashMap<String, ArrayList<Task>> queues = new HashMap<>();
// Roster witch holds information about which executor is assigned to a task // Roster witch holds information about which executor is assigned to a task
private HashMap<String, RosterItem> rosterMap = new HashMap<>(); private final HashMap<String, RosterItem> rosterMap = new HashMap<>();
Logger logger = Logger.getLogger(Roster.class.getName()); Logger logger = Logger.getLogger(Roster.class.getName());

View File

@ -6,13 +6,13 @@ import lombok.Getter;
public class RosterItem { public class RosterItem {
@Getter @Getter
private String taskID; private final String taskID;
@Getter @Getter
private String taskType; private final String taskType;
@Getter @Getter
private ExecutorURI executorURI; private final ExecutorURI executorURI;
public RosterItem(String taskID, String taskType, ExecutorURI executorURI) { public RosterItem(String taskID, String taskType, ExecutorURI executorURI) {
this.taskID = taskID; this.taskID = taskID;

View File

@ -28,41 +28,40 @@ public class AddNewAssignmentToRosterServiceSystemTest {
@Test @Test
void addNewAssignmentToRosterService() throws JSONException { void addNewAssignmentToRosterService() throws JSONException {
String rosterItemId = "TEST-ID"; String taskId = "TEST-ID";
String executorType = "TEST-TYPE"; String executorType = "TEST-TYPE";
String inputData = "TEST-DATA";
String executorURI = "TEST-URI"; String executorURI = "TEST-URI";
ResponseEntity response = whenAddNewAssignmentToRoster(rosterItemId, executorType, executorURI); ResponseEntity response = whenAddNewAssignmentToRoster(taskId, executorType, inputData, executorURI);
System.out.println(response.getBody().toString());
JSONObject responseJson = new JSONObject(response.getBody().toString()); JSONObject responseJson = new JSONObject(response.getBody().toString());
String respExecutorType = responseJson.getString("executorType"); String respTaskId = responseJson.getString("taskID");
String respExecutorURI = responseJson.getString("executorURI"); String respTaskType = responseJson.getJSONObject("taskType").getString("value");
String respInputData = responseJson.getString("inputData");
then(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); then(response.getStatusCode()).isEqualTo(HttpStatus.OK);
then(respExecutorType).isEqualTo(executorType); then(respTaskId).isEqualTo(respTaskId);
then(respExecutorURI).isEqualTo(executorURI); then(respTaskType).isEqualTo(executorType);
then(respInputData).isEqualTo(inputData);
then(Roster.getInstance().getRosterMap().size()).isEqualTo(1); then(Roster.getInstance().getRosterMap().size()).isEqualTo(1);
} }
private ResponseEntity whenAddNewAssignmentToRoster( private ResponseEntity whenAddNewAssignmentToRoster(
String rosterItemId, String taskId,
String executorType, String executorType,
String inputData,
String executorURI) throws JSONException { String executorURI) throws JSONException {
Roster roster = Roster.getInstance(); Roster roster = Roster.getInstance();
roster.getRosterMap().clear(); roster.getRosterMap().clear();
roster.addTaskToQueue(new Task(rosterItemId, new ExecutorType(executorType), executorURI)); roster.addTaskToQueue(new Task(taskId, new ExecutorType(executorType), inputData));
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json"); headers.add("Content-Type", "application/json");
String jsonPayLoad = new JSONObject() String jsonPayLoad = new JSONObject()
.put("rosterItemId", rosterItemId)
.put("executorType", executorType) .put("executorType", executorType)
.put("executorURI", executorURI) .put("executorURI", executorURI)
.toString(); .toString();

View File

@ -5,6 +5,7 @@ import ch.unisg.common.valueobject.ExecutorURI;
import ch.unisg.roster.roster.adapter.out.persistence.mongodb.RosterRepository; import ch.unisg.roster.roster.adapter.out.persistence.mongodb.RosterRepository;
import ch.unisg.roster.roster.application.port.in.ApplyForTaskCommand; import ch.unisg.roster.roster.application.port.in.ApplyForTaskCommand;
import ch.unisg.roster.roster.application.port.in.ApplyForTaskUseCase; import ch.unisg.roster.roster.application.port.in.ApplyForTaskUseCase;
import ch.unisg.roster.roster.application.port.in.LoadRosterItemPort;
import ch.unisg.roster.roster.domain.RosterItem; import ch.unisg.roster.roster.domain.RosterItem;
import ch.unisg.roster.roster.domain.Task; import ch.unisg.roster.roster.domain.Task;
import ch.unisg.roster.roster.domain.valueobject.ExecutorType; import ch.unisg.roster.roster.domain.valueobject.ExecutorType;
@ -15,7 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.then; import static org.mockito.BDDMockito.then;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -29,6 +30,9 @@ public class ApplyForTaskWebControllerTest {
@MockBean @MockBean
private ApplyForTaskUseCase applyForTaskUseCase; private ApplyForTaskUseCase applyForTaskUseCase;
@MockBean
private LoadRosterItemPort loadRosterItemPort;
@MockBean @MockBean
RosterRepository rosterRepository; RosterRepository rosterRepository;
@ -55,14 +59,13 @@ public class ApplyForTaskWebControllerTest {
Mockito.when(applyForTaskUseCase.applyForTask(applyForTaskCommand)) Mockito.when(applyForTaskUseCase.applyForTask(applyForTaskCommand))
.thenReturn(taskStub); .thenReturn(taskStub);
mockMvc.perform(post("/task/apply/") mockMvc.perform(post("/task/apply/")
.contentType("application/json") .contentType("application/json")
.content(jsonPayLoad)) .content(jsonPayLoad))
.andExpect(status().is2xxSuccessful()); .andExpect(status().is2xxSuccessful());
then(applyForTaskUseCase).should() then(applyForTaskUseCase).should()
.applyForTask(new ApplyForTaskCommand(new ExecutorType(executorType), new ExecutorURI(executorURI))); .applyForTask(eq(new ApplyForTaskCommand(new ExecutorType(executorType), new ExecutorURI(executorURI))));
} }
} }

View File

@ -38,7 +38,6 @@ public class RosterPersistenceAdapterTest {
new ExecutorURI(executorURI) new ExecutorURI(executorURI)
); );
adapterUnderTest.addRosterItem(testRosterItem); adapterUnderTest.addRosterItem(testRosterItem);
MongoRosterDocument retrievedDoc = rosterRepository.findByTaskId(taskId); MongoRosterDocument retrievedDoc = rosterRepository.findByTaskId(taskId);
@ -46,7 +45,6 @@ public class RosterPersistenceAdapterTest {
assertThat(retrievedDoc.taskId).isEqualTo(taskId); assertThat(retrievedDoc.taskId).isEqualTo(taskId);
assertThat(retrievedDoc.executorURI).isEqualTo(executorURI); assertThat(retrievedDoc.executorURI).isEqualTo(executorURI);
assertThat(retrievedDoc.taskType).isEqualTo(executorType); assertThat(retrievedDoc.taskType).isEqualTo(executorType);
} }
@Test @Test

View File

@ -41,7 +41,6 @@ public class AddNewAssignmentToRosterServiceTest {
Task newTask = givenATaskWithIdAndType("TEST-ID", "TEST-TYPE", "TEST-INPUT"); Task newTask = givenATaskWithIdAndType("TEST-ID", "TEST-TYPE", "TEST-INPUT");
RosterItem newRosterItem = givenARosterItemWithIdAndTypeAndExecutorUri("TEST-ID", "TEST-TYPE", "TEST-URI"); RosterItem newRosterItem = givenARosterItemWithIdAndTypeAndExecutorUri("TEST-ID", "TEST-TYPE", "TEST-URI");
// TODO Add task to queue
Roster roster = Roster.getInstance(); Roster roster = Roster.getInstance();
roster.addTaskToQueue(newTask); roster.addTaskToQueue(newTask);
@ -50,6 +49,8 @@ public class AddNewAssignmentToRosterServiceTest {
Task assignedTask = applyForTaskService.applyForTask(applyForTaskCommand); Task assignedTask = applyForTaskService.applyForTask(applyForTaskCommand);
assertThat(assignedTask).isNotNull(); assertThat(assignedTask).isNotNull();
// Checks that the first (and only) task type has no tasks
assertThat(roster.getAllTasksFromQueue().stream().findFirst().get()).hasSize(0);
then(taskAssignedEventPort).should(times(1)) then(taskAssignedEventPort).should(times(1))
.publishTaskAssignedEvent(any(TaskAssignedEvent.class)); .publishTaskAssignedEvent(any(TaskAssignedEvent.class));

View File

@ -28,13 +28,8 @@ public class RosterTest {
assertThat(rosterMap.iterator().next().getTaskType()).isEqualTo("TEST-TYPE"); assertThat(rosterMap.iterator().next().getTaskType()).isEqualTo("TEST-TYPE");
assertThat(rosterMap.iterator().next().getExecutorURI().getValue().toString()).isEqualTo("TEST-URI"); assertThat(rosterMap.iterator().next().getExecutorURI().getValue().toString()).isEqualTo("TEST-URI");
assertThat(task.getTaskType().getValue().toString()).isEqualTo("TEST-TYPE"); assertThat(task.getTaskType().getValue()).isEqualTo("TEST-TYPE");
assertThat(task.getTaskID()).isEqualTo("TEST-ID"); assertThat(task.getTaskID()).isEqualTo("TEST-ID");
boolean empty_queue = roster.deleteTask("TEST-ID");
// TODO test that the task was removed from the Queue similar to below --> I don't know if it actually gets deleted or not
//assertThat(empty_queue).isEqualTo(true);
//assertThat(queues.size()).isEqualTo(0);
} }
@Test @Test
@ -45,8 +40,8 @@ public class RosterTest {
roster.addTaskToQueue(new Task("TEST-ID", "TEST-TYPE")); roster.addTaskToQueue(new Task("TEST-ID", "TEST-TYPE"));
boolean test = roster.deleteTask("TEST-ID"); boolean test = roster.deleteTask("TEST-ID");
// TODO Fix assert for queue
assertThat(test).isEqualTo(true); assertThat(test).isEqualTo(true);
assertThat(queues.size()).isEqualTo(1); // Checks that the first (and only) task type has no tasks
assertThat(queues.stream().findFirst().get()).hasSize(0);
} }
} }

View File

@ -36,7 +36,7 @@ public class TapasAuctionHouseApplication {
SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class); SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class);
ENVIRONMENT = tapasAuctioneerApp.run(args).getEnvironment(); ENVIRONMENT = tapasAuctioneerApp.run(args).getEnvironment();
// TODO Set start up of message services with config // TODO Set start up of message services with config
// We will use these bootstrap methods in Week 6:
bootstrapMarketplaceWithWebSub(); bootstrapMarketplaceWithWebSub();
bootstrapMarketplaceWithMqtt(); bootstrapMarketplaceWithMqtt();
var getExecutorsService = new GetExecutorsService(); var getExecutorsService = new GetExecutorsService();
@ -56,12 +56,6 @@ public class TapasAuctionHouseApplication {
subscriber.subscribeToAuctionHouseEndpoint(endpoint.getWebSubUri().getValue()); subscriber.subscribeToAuctionHouseEndpoint(endpoint.getWebSubUri().getValue());
} }
} }
// try {
// subscriber.subscribeToAuctionHouseEndpoint(new URI("http://6b4e-130-82-250-227.ngrok.io/websub-discovery"));
// } catch (URISyntaxException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
} }
/** /**

View File

@ -7,5 +7,5 @@ import org.eclipse.paho.client.mqttv3.MqttMessage;
*/ */
public abstract class AuctionEventMqttListener { public abstract class AuctionEventMqttListener {
public abstract boolean handleEvent(MqttMessage message); public abstract void handleEvent(MqttMessage message);
} }

View File

@ -20,7 +20,7 @@ public class BidReceivedEventListenerMqttAdapter extends AuctionEventMqttListene
private static final Logger LOGGER = LogManager.getLogger(BidReceivedEventListenerMqttAdapter.class); private static final Logger LOGGER = LogManager.getLogger(BidReceivedEventListenerMqttAdapter.class);
@Override @Override
public boolean handleEvent(MqttMessage message){ public void handleEvent(MqttMessage message){
String payload = new String(message.getPayload()); String payload = new String(message.getPayload());
try { try {
@ -44,9 +44,7 @@ public class BidReceivedEventListenerMqttAdapter extends AuctionEventMqttListene
bidReceivedHandler.handleNewBidReceivedEvent(bidReceivedEvent); bidReceivedHandler.handleNewBidReceivedEvent(bidReceivedEvent);
} catch (JsonProcessingException | NullPointerException e) { } catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e); LOGGER.error(e.getMessage(), e);
return false;
} }
return true;
} }
} }

View File

@ -23,7 +23,7 @@ public class ExecutorAddedEventListenerMqttAdapter extends AuctionEventMqttListe
private static final Logger LOGGER = LogManager.getLogger(ExecutorAddedEventListenerMqttAdapter.class); private static final Logger LOGGER = LogManager.getLogger(ExecutorAddedEventListenerMqttAdapter.class);
@Override @Override
public boolean handleEvent(MqttMessage message) { public void handleEvent(MqttMessage message) {
String payload = new String(message.getPayload()); String payload = new String(message.getPayload());
try { try {
@ -43,9 +43,7 @@ public class ExecutorAddedEventListenerMqttAdapter extends AuctionEventMqttListe
newExecutorHandler.handleNewExecutorEvent(executorAddedEvent); newExecutorHandler.handleNewExecutorEvent(executorAddedEvent);
} catch (JsonProcessingException | NullPointerException e) { } catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e); LOGGER.error(e.getMessage(), e);
return false;
} }
return true;
} }
} }

View File

@ -23,7 +23,7 @@ public class ExecutorRemovedEventListenerMqttAdapter extends AuctionEventMqttLis
private static final Logger LOGGER = LogManager.getLogger(ExecutorRemovedEventListenerMqttAdapter.class); private static final Logger LOGGER = LogManager.getLogger(ExecutorRemovedEventListenerMqttAdapter.class);
@Override @Override
public boolean handleEvent(MqttMessage message) { public void handleEvent(MqttMessage message) {
String payload = new String(message.getPayload()); String payload = new String(message.getPayload());
try { try {
@ -41,9 +41,6 @@ public class ExecutorRemovedEventListenerMqttAdapter extends AuctionEventMqttLis
newExecutorHandler.handleExecutorRemovedEvent(executorRemovedEvent); newExecutorHandler.handleExecutorRemovedEvent(executorRemovedEvent);
} catch (JsonProcessingException | NullPointerException e) { } catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e); LOGGER.error(e.getMessage(), e);
return false;
} }
return true;
} }
} }

View File

@ -1,12 +1,8 @@
package ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt; package ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation; import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.TaskJsonRepresentation; import ch.unisg.tapas.auctionhouse.application.port.in.AuctionStartedEvent;
import ch.unisg.tapas.auctionhouse.application.handler.BidReceivedHandler;
import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEvent;
import ch.unisg.tapas.auctionhouse.domain.Auction; import ch.unisg.tapas.auctionhouse.domain.Auction;
import ch.unisg.tapas.auctionhouse.domain.Bid;
import ch.unisg.tapas.auctionhouse.domain.ExecutorRegistry;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -14,23 +10,17 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.http.HttpClient; import java.sql.Timestamp;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ExternalAuctionStartedEventListenerMqttAdapter extends AuctionEventMqttListener{ public class ExternalAuctionStartedEventListenerMqttAdapter extends AuctionEventMqttListener{
private static final Logger LOGGER = LogManager.getLogger(ExternalAuctionStartedEventListenerMqttAdapter.class); private static final Logger LOGGER = LogManager.getLogger(ExternalAuctionStartedEventListenerMqttAdapter.class);
String auctionHouseURI = "https://tapas-auction-house.86-119-35-40.nip.io/";
String taskListURI = "https://tapas-tasks.86-119-35-40.nip.io";
@Override @Override
public boolean handleEvent(MqttMessage message){ public void handleEvent(MqttMessage message){
String payload = new String(message.getPayload()); String payload = new String(message.getPayload());
System.out.println("New auction"); System.out.println("New external MQTT auction");
try { try {
// Note: this message representation is provided only as an example. You should use a // Note: this message representation is provided only as an example. You should use a
@ -44,46 +34,21 @@ public class ExternalAuctionStartedEventListenerMqttAdapter extends AuctionEvent
String taskType = data.get("taskType").asText(); String taskType = data.get("taskType").asText();
String deadline = data.get("deadline").asText(); String deadline = data.get("deadline").asText();
var capable = ExecutorRegistry.getInstance().containsTaskType(new Auction.AuctionedTaskType(taskType)); var auction = new Auction(
System.out.println("Capable: " + capable); new Auction.AuctionId(auctionId),
// TODO check deadline new Auction.AuctionHouseUri(URI.create(auctionHouseUri)),
if(capable){ new Auction.AuctionedTaskUri(URI.create(taskUri)),
var bid = new Bid( new Auction.AuctionedTaskType(taskType),
new Auction.AuctionId(auctionId), new Auction.AuctionDeadline(Timestamp.valueOf(deadline))
new Bid.BidderName("Group-1"), );
new Bid.BidderAuctionHouseUri(URI.create(auctionHouseURI)),
new Bid.BidderTaskListUri(URI.create(taskListURI))
);
String body = BidJsonRepresentation.serialize(bid); var event = new AuctionStartedEvent(auction);
LOGGER.info(body); var handler = new AuctionStartedHandler();
var postURI = URI.create(auctionHouseUri + "/bid"); handler.handleAuctionStartedEvent(event);
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(postURI)
.header("Content-Type", BidJsonRepresentation.MEDIA_TYPE)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpClient client = HttpClient.newHttpClient();
var postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
LOGGER.info(postResponse.statusCode()); } catch (JsonProcessingException e) {
}
} catch (JsonProcessingException | NullPointerException e) {
LOGGER.error(e.getMessage(), e);
return false;
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
e.printStackTrace(); e.printStackTrace();
} catch (InterruptedException e) {
LOGGER.error(e.getMessage(), e);
e.printStackTrace();
} catch (Exception e){
LOGGER.error(e.getMessage(), e);
} }
return true;
} }
} }

View File

@ -1,104 +0,0 @@
package ch.unisg.tapas.auctionhouse.adapter.in.messaging.websub;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.AuctionJsonRepresentation;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation;
import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler;
import ch.unisg.tapas.auctionhouse.application.port.in.AuctionStartedEvent;
import ch.unisg.tapas.auctionhouse.domain.Auction;
import ch.unisg.tapas.auctionhouse.domain.Bid;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionDeadline;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionHouseUri;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionId;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskType;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskUri;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.Timestamp;
import java.util.Collection;
import java.util.Date;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* This class is a template for handling auction started events received via WebSub
*/
@RestController
public class AuctionStartedEventListenerWebSubAdapter {
private final AuctionStartedHandler auctionStartedHandler;
public AuctionStartedEventListenerWebSubAdapter(AuctionStartedHandler auctionStartedHandler) {
this.auctionStartedHandler = auctionStartedHandler;
}
/**
* Controller which listens to auction-started callbacks
* @return 200 OK
* @throws URISyntaxException
**/
// TODO generate a new capability ID instead of using a hardcoded one.
@PostMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c")
public ResponseEntity<Void> handleExecutorAddedEvent(@RequestBody String payload) throws URISyntaxException {
System.out.println("new websub auctions");
System.out.println(payload);
JSONArray auctions = new JSONArray(payload);
if (auctions.length() > 0) {
JSONObject auction = auctions.getJSONObject(0);
System.out.print(auction);
String auctionHouseURI = "https://tapas-auction-house.86-119-35-40.nip.io/";
String taskListURI = "https://tapas-tasks.86-119-35-40.nip.io";
// TODO Sanitize URIs
String auctionId = auction.getString("auctionId");
String auctionHouseUri = auction.getString("auctionHouseUri");
var bid = new Bid(
new Auction.AuctionId(auctionId),
new Bid.BidderName("Group-1"),
new Bid.BidderAuctionHouseUri(URI.create(auctionHouseURI)),
new Bid.BidderTaskListUri(URI.create(taskListURI))
);
String body;
try {
body = BidJsonRepresentation.serialize(bid);
//LOGGER.info(body);
var postURI = URI.create(auctionHouseUri + "/bid");
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(postURI)
.header("Content-Type", BidJsonRepresentation.MEDIA_TYPE)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpClient client = HttpClient.newHttpClient();
var postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -0,0 +1,66 @@
package ch.unisg.tapas.auctionhouse.adapter.in.messaging.websub;
import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler;
import ch.unisg.tapas.auctionhouse.application.port.in.AuctionStartedEvent;
import ch.unisg.tapas.auctionhouse.domain.Auction;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Timestamp;
/**
* This class is a template for handling auction started events received via WebSub
*/
@RestController
public class ExternalAuctionStartedEventListenerWebSubAdapter {
private final AuctionStartedHandler auctionStartedHandler;
public ExternalAuctionStartedEventListenerWebSubAdapter(AuctionStartedHandler auctionStartedHandler) {
this.auctionStartedHandler = auctionStartedHandler;
}
/**
* Controller which listens to auction-started callbacks
* @return 200 OK
* @throws URISyntaxException
**/
// TODO generate a new capability ID instead of using a hardcoded one.
@PostMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c")
public ResponseEntity<Void> handleExecutorAddedEvent(@RequestBody String payload) throws URISyntaxException {
System.out.println("New external WebSub auction");
System.out.println(payload);
JSONArray auctions = new JSONArray(payload);
if (auctions.length() > 0) {
JSONObject auctionJson = auctions.getJSONObject(0);
System.out.print(auctionJson);
String auctionId = auctionJson.getString("auctionId");
String auctionHouseUri = auctionJson.getString("auctionHouseUri");
String taskUri = auctionJson.getString("taskUri");
String taskType = auctionJson.getString("taskType");
String deadline = auctionJson.getString("deadline");
var auction = new Auction(
new Auction.AuctionId(auctionId),
new Auction.AuctionHouseUri(URI.create(auctionHouseUri)),
new Auction.AuctionedTaskUri(URI.create(taskUri)),
new Auction.AuctionedTaskType(taskType),
new Auction.AuctionDeadline(Timestamp.valueOf(deadline))
);
var event = new AuctionStartedEvent(auction);
auctionStartedHandler.handleAuctionStartedEvent(event);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -53,13 +53,13 @@ public class AuctionHouseDiscoveryHttpAdapter implements AuctionHouseDiscoveryPo
return returnList; return returnList;
} }
return Collections.<AuctionHouseDiscoveryInformation>emptyList(); return Collections.emptyList();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return Collections.<AuctionHouseDiscoveryInformation>emptyList(); return Collections.emptyList();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
return Collections.<AuctionHouseDiscoveryInformation>emptyList(); return Collections.emptyList();
} }
} }

View File

@ -1,19 +1,48 @@
package ch.unisg.tapas.auctionhouse.adapter.out.web; package ch.unisg.tapas.auctionhouse.adapter.out.web;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation;
import ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt.ExternalAuctionStartedEventListenerMqttAdapter;
import ch.unisg.tapas.auctionhouse.application.port.out.PlaceBidForAuctionCommand; import ch.unisg.tapas.auctionhouse.application.port.out.PlaceBidForAuctionCommand;
import ch.unisg.tapas.auctionhouse.application.port.out.PlaceBidForAuctionCommandPort; import ch.unisg.tapas.auctionhouse.application.port.out.PlaceBidForAuctionCommandPort;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** import java.io.IOException;
* This class is a tempalte for implementing a place bid for auction command via HTTP. import java.net.http.HttpClient;
*/ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
@Component @Component
@Primary @Primary
public class PlaceBidForAuctionCommandHttpAdapter implements PlaceBidForAuctionCommandPort { public class PlaceBidForAuctionCommandHttpAdapter implements PlaceBidForAuctionCommandPort {
private static final Logger LOGGER = LogManager.getLogger(PlaceBidForAuctionCommandHttpAdapter.class);
@Override @Override
public void placeBid(PlaceBidForAuctionCommand command) { public void placeBid(PlaceBidForAuctionCommand command) {
// TODO try{
var body = BidJsonRepresentation.serialize(command.getBid());
LOGGER.info("Body of bid to be bid:" + body);
var postRequest = HttpRequest.newBuilder()
.uri(command.getAuction().getAuctionHouseUri().getValue())
.header("Content-Type", BidJsonRepresentation.MEDIA_TYPE)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpClient client = HttpClient.newHttpClient();
var postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
LOGGER.info(postResponse.statusCode());
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }

View File

@ -37,7 +37,12 @@ public class AuctionStartedHandler implements AuctionStartedEventHandler {
public boolean handleAuctionStartedEvent(AuctionStartedEvent auctionStartedEvent) { public boolean handleAuctionStartedEvent(AuctionStartedEvent auctionStartedEvent) {
Auction auction = auctionStartedEvent.getAuction(); Auction auction = auctionStartedEvent.getAuction();
if (ExecutorRegistry.getInstance().containsTaskType(auction.getTaskType())) { var capable = ExecutorRegistry.getInstance().containsTaskType(auction.getTaskType());
var auctionOngoing = !auction.deadlineHasPassed();
System.out.println("Capable: " + capable);
System.out.println("Auction ongoing: " + auction.deadlineHasPassed());
if(capable && auctionOngoing){
LOGGER.info("Placing bid for task " + auction.getTaskUri() + " of type " LOGGER.info("Placing bid for task " + auction.getTaskUri() + " of type "
+ auction.getTaskType() + " in auction " + auction.getAuctionId() + auction.getTaskType() + " in auction " + auction.getAuctionId()
+ " from auction house " + auction.getAuctionHouseUri().getValue().toString()); + " from auction house " + auction.getAuctionHouseUri().getValue().toString());
@ -50,7 +55,8 @@ public class AuctionStartedHandler implements AuctionStartedEventHandler {
PlaceBidForAuctionCommand command = new PlaceBidForAuctionCommand(auction, bid); PlaceBidForAuctionCommand command = new PlaceBidForAuctionCommand(auction, bid);
placeBidForAuctionCommandPort.placeBid(command); placeBidForAuctionCommandPort.placeBid(command);
} else { }
else if(!capable) {
LOGGER.info("Cannot execute this task type: " + auction.getTaskType().getValue()); LOGGER.info("Cannot execute this task type: " + auction.getTaskType().getValue());
} }

View File

@ -5,6 +5,7 @@ import lombok.Value;
import java.net.URI; import java.net.URI;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
/** /**
@ -129,6 +130,17 @@ public class Auction {
return auctionStatus.getValue() == Status.OPEN; return auctionStatus.getValue() == Status.OPEN;
} }
/**
* Checks if the deadline has passed.
* Useful to check if external auctions are finished.
*
* @return true if deadline is greater than current timestamp, false otherwise
*/
public boolean deadlineHasPassed() {
var currentTime = new Timestamp(System.currentTimeMillis());
return currentTime.before(deadline.getValue());
}
/** /**
* Closes the auction. Called by the StartAuctionService after the auction deadline has expired. * Closes the auction. Called by the StartAuctionService after the auction deadline has expired.
*/ */

View File

@ -25,7 +25,7 @@ public class AuctionHouseDiscovery {
// static String AUCTION_HOUSE_URI = "http://localhost:8086"; // static String AUCTION_HOUSE_URI = "http://localhost:8086";
@Getter @Getter
private List<AuctionHouseDiscoveryInformation> auctionHouseDiscoveryList = new ArrayList<>() { private final List<AuctionHouseDiscoveryInformation> auctionHouseDiscoveryList = new ArrayList<>() {
}; };
private AuctionHouseDiscovery() { private AuctionHouseDiscovery() {

View File

@ -7,7 +7,7 @@ import lombok.Getter;
*/ */
public class AuctionStartedEvent { public class AuctionStartedEvent {
@Getter @Getter
private Auction auction; private final Auction auction;
public AuctionStartedEvent(Auction auction) { public AuctionStartedEvent(Auction auction) {
this.auction = auction; this.auction = auction;

View File

@ -8,7 +8,7 @@ import lombok.Getter;
public class AuctionWonEvent { public class AuctionWonEvent {
// The winning bid // The winning bid
@Getter @Getter
private Bid winningBid; private final Bid winningBid;
public AuctionWonEvent(Bid winningBid) { public AuctionWonEvent(Bid winningBid) {
this.winningBid = winningBid; this.winningBid = winningBid;

View File

@ -31,12 +31,12 @@ public class AuctionHouseResourceDirectory {
this.rdEndpoint = rdEndpoint; this.rdEndpoint = rdEndpoint;
} }
private AuctionHouseDiscoveryPort auctionHouseDiscoveryport = new AuctionHouseDiscoveryHttpAdapter(); private final AuctionHouseDiscoveryPort auctionHouseDiscoveryport = new AuctionHouseDiscoveryHttpAdapter();
private List<AuctionHouseDiscoveryInformation> auctionHouseEndpoints = new ArrayList<>(); private final List<AuctionHouseDiscoveryInformation> auctionHouseEndpoints = new ArrayList<>();
// List to keep track of already fetched endpoints // List to keep track of already fetched endpoints
private List<URI> fetchedEndpoints = new ArrayList<>(); private final List<URI> fetchedEndpoints = new ArrayList<>();
/** /**
* Retrieves the endpoints of all auctions houses registered with this directory. * Retrieves the endpoints of all auctions houses registered with this directory.

View File

@ -5,7 +5,7 @@ import java.util.Set;
public class SelfValidating<T> { public class SelfValidating<T> {
private Validator validator; private final Validator validator;
public SelfValidating() { public SelfValidating() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

View File

@ -9,7 +9,7 @@ import java.util.Set;
public abstract class SelfValidating<T> { public abstract class SelfValidating<T> {
private Validator validator; private final Validator validator;
public SelfValidating() { public SelfValidating() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

View File

@ -8,9 +8,9 @@ import java.util.List;
@Repository @Repository
public interface TaskRepository extends MongoRepository<MongoTaskDocument,String> { public interface TaskRepository extends MongoRepository<MongoTaskDocument,String> {
public MongoTaskDocument findByTaskId(String taskId); MongoTaskDocument findByTaskId(String taskId);
public List<MongoTaskDocument> getAllBy(); List<MongoTaskDocument> getAllBy();
public void deleteByTaskId(String taskId); void deleteByTaskId(String taskId);
} }

View File

@ -8,8 +8,8 @@ import java.util.List;
public class Adapters extends ArchitectureElement { public class Adapters extends ArchitectureElement {
private final HexagonalArchitecture parentContext; private final HexagonalArchitecture parentContext;
private List<String> incomingAdapterPackages = new ArrayList<>(); private final List<String> incomingAdapterPackages = new ArrayList<>();
private List<String> outgoingAdapterPackages = new ArrayList<>(); private final List<String> outgoingAdapterPackages = new ArrayList<>();
Adapters(HexagonalArchitecture parentContext, String basePackage) { Adapters(HexagonalArchitecture parentContext, String basePackage) {
super(basePackage); super(basePackage);

View File

@ -8,9 +8,9 @@ import java.util.List;
public class ApplicationLayer extends ArchitectureElement { public class ApplicationLayer extends ArchitectureElement {
private final HexagonalArchitecture parentContext; private final HexagonalArchitecture parentContext;
private List<String> incomingPortsPackages = new ArrayList<>(); private final List<String> incomingPortsPackages = new ArrayList<>();
private List<String> outgoingPortsPackages = new ArrayList<>(); private final List<String> outgoingPortsPackages = new ArrayList<>();
private List<String> servicePackages = new ArrayList<>(); private final List<String> servicePackages = new ArrayList<>();
public ApplicationLayer(String basePackage, HexagonalArchitecture parentContext) { public ApplicationLayer(String basePackage, HexagonalArchitecture parentContext) {
super(basePackage); super(basePackage);

View File

@ -11,7 +11,7 @@ public class HexagonalArchitecture extends ArchitectureElement {
private Adapters adapters; private Adapters adapters;
private ApplicationLayer applicationLayer; private ApplicationLayer applicationLayer;
private String configurationPackage; private String configurationPackage;
private List<String> domainPackages = new ArrayList<>(); private final List<String> domainPackages = new ArrayList<>();
public static HexagonalArchitecture boundedContext(String basePackage) { public static HexagonalArchitecture boundedContext(String basePackage) {
return new HexagonalArchitecture(basePackage); return new HexagonalArchitecture(basePackage);