From c87a732e2af370e48fdee72fd478c62fe36ac78e Mon Sep 17 00:00:00 2001 From: "julius.lautz" Date: Sat, 11 Dec 2021 18:36:23 +0100 Subject: [PATCH 01/12] added executor-humidity --- .../service/NotifyExecutorPoolService.java | 2 +- .../executor/domain/ExecutorType.java | 4 +- executor-humidity/pom.xml | 36 ++++++++++++++++++ .../ExecutorhumidityApplication.java | 16 ++++++++ .../in/web/TaskAvailableController.java | 38 +++++++++++++++++++ .../adapter/out/GetHumidityAdapter.java | 17 +++++++++ .../application/port/out/GetHumidityPort.java | 5 +++ .../service/TaskAvailableService.java | 27 +++++++++++++ .../executor/domain/Executor.java | 22 +++++++++++ 9 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 executor-humidity/pom.xml create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java create mode 100644 executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java index aee3142..64b6d23 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java @@ -1,4 +1,4 @@ -package ch.unisg.executorbase.executor.application.service; +package ch.unisg.executorBase.executor.application.service; import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.executorbase.executor.application.port.out.NotifyExecutorPoolPort; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java index ca9533a..8905baa 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java @@ -1,11 +1,11 @@ package ch.unisg.executorbase.executor.domain; public enum ExecutorType { - ADDITION, ROBOT; + ADDITION, ROBOT, HUMIDITY; /** * Checks if the give executor type exists. - * @return Wheter the given executor type exists + * @return Whether the given executor type exists **/ public static boolean contains(String test) { diff --git a/executor-humidity/pom.xml b/executor-humidity/pom.xml new file mode 100644 index 0000000..3c07d0c --- /dev/null +++ b/executor-humidity/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.example + executor-miro + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-autoconfigure + 2.5.5 + compile + + + org.springframework.boot + spring-boot-autoconfigure + 2.5.5 + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + + + 16 + 16 + + + diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java new file mode 100644 index 0000000..181cfeb --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/ExecutorhumidityApplication.java @@ -0,0 +1,16 @@ +package ch.unisg.executorhumidity; + + +import ch.unisg.executorhumidity.executor.domain.Executor; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExecutorhumidityApplication { + + public static void main(String[] args) { + SpringApplication.run(ExecutorhumidityApplication.class, args); + Executor.getExecutor(); + } + +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java new file mode 100644 index 0000000..be85ab8 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java @@ -0,0 +1,38 @@ +package ch.unisg.executorhumidity.executor.adapter.in.web; + +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.RestController; + +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableCommand; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableUseCase; +import ch.unisg.executorbase.executor.domain.ExecutorType; + +import java.util.concurrent.CompletableFuture; + +@RestController +public class TaskAvailableController { + private final TaskAvailableUseCase taskAvailableUseCase; + + public TaskAvailableController(TaskAvailableUseCase taskAvailableUseCase) { + this.taskAvailableUseCase = taskAvailableUseCase; + } + + @GetMapping(path="/newtask/{taskType}") + public ResponseEntity retrieveTaskfromTaskList(@PathVariable("taskType") String taskType) { + + if (ExecutorType.contains(taskType.toUpperCase())) { + TaskAvailableCommand command = new TaskAvailableCommand( + ExecutorType.valueOf(taskType.toUpperCase())); + CompletableFuture.runAsync(() -> taskAvailableUseCase.newTaskAvailable(command); + } + + // Add the content type as a response header + HttpHeaders responseHeaders = new HttpHeaders(); + + return new ResponseEntity<>("OK", responseHeaders, HttpStatus.OK); + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java new file mode 100644 index 0000000..88f440d --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java @@ -0,0 +1,17 @@ +package ch.unisg.executorhumidity.executor.adapter.out; + +import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@Primary +public class GetHumidityAdapter implements GetHumidityPort { + + @Override + public boolean getHumidity(String key) { + + CoapClient client1 = new CoapClient("coap://130.82.171.10:5683/humidity") + + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java new file mode 100644 index 0000000..b865cfd --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java @@ -0,0 +1,5 @@ +package ch.unisg.executorhumidity.executor.application.port.out; + +public interface GetHumidityPort { + boolean getHumidity(String key); +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java new file mode 100644 index 0000000..0e467c4 --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/service/TaskAvailableService.java @@ -0,0 +1,27 @@ +package ch.unisg.executorhumidity.executor.application.service; + +import ch.unisg.executorbase.executor.domain.ExecutorStatus; +import ch.unisg.executorhumidity.executor.domain.Executor; +import org.springframework.stereotype.Component; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableCommand; +import ch.unisg.executorbase.executor.application.port.in.TaskAvailableUseCase; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@RequiredArgsConstructor +@Component +@Transactional +public class TaskAvailableService implements TaskAvailableUseCase { + + @Override + public void newTaskAvailable(TaskAvailableCommand command) { + + Executor executor = Executor.getExecutor(); + + if(executor.getExecutorType() == command.getTaskType() && + executor.getStatus() == ExecutorStatus.IDLING) { + executor.getAssignment(); + } + } +} diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java new file mode 100644 index 0000000..2a8cd3c --- /dev/null +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java @@ -0,0 +1,22 @@ +package ch.unisg.executorhumidity.executor.domain; + +import ch.unisg.executorbase.executor.domain.ExecutorBase; +import ch.unisg.executorbase.executor.domain.ExecutorType; + +public class Executor extends ExecutorBase{ + + private static final Executor executor = new Exec(ExecutorType.HUMIDITY); + // TODO: Add the necessary ports + + + private Executor(ExecutorType executorType) {super(executorType);} + + public static Executor getExecutor() {return executor;} + + + @Override + protected + String execution(String input) { + //TODO: Fill + } +} -- 2.45.1 From aaffb0371e30790eacc334ea47b0127dcb8760ab Mon Sep 17 00:00:00 2001 From: "julius.lautz" Date: Sat, 11 Dec 2021 19:09:34 +0100 Subject: [PATCH 02/12] made changes to executor-humidity --- .../executor/domain/ExecutorBase.java | 3 +- executor-humidity/pom.xml | 13 +++++--- .../adapter/out/GetHumidityAdapter.java | 19 +++++++++-- .../application/port/out/GetHumidityPort.java | 6 +++- .../executor/domain/Executor.java | 12 ++++++- executor-robot/pom.xml | 32 ++++++++++++++++++- 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java index 09ded48..5f125f2 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java @@ -1,5 +1,6 @@ package ch.unisg.executorbase.executor.domain; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -88,6 +89,6 @@ public abstract class ExecutorBase { * Implementation of the actual execution method of an executor * @return the execution result **/ - protected abstract String execution(String input); + protected abstract String execution(String input) throws ConnectorException, IOException, ConnectorException; } diff --git a/executor-humidity/pom.xml b/executor-humidity/pom.xml index 3c07d0c..6828a7d 100644 --- a/executor-humidity/pom.xml +++ b/executor-humidity/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.example - executor-miro + executor-humidity 1.0-SNAPSHOT @@ -15,9 +15,9 @@ compile - org.springframework.boot - spring-boot-autoconfigure - 2.5.5 + org.springframework + spring-web + 5.3.10 compile @@ -26,6 +26,11 @@ 0.0.1-SNAPSHOT compile + + org.eclipse.californium + californium-core + 3.0.0 + diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java index 88f440d..5cf9c88 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java @@ -1,17 +1,32 @@ package ch.unisg.executorhumidity.executor.adapter.out; import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import org.eclipse.californium.core.CoapClient; +import org.eclipse.californium.elements.exception.ConnectorException; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; +import java.io.IOException; + + @Component @Primary public class GetHumidityAdapter implements GetHumidityPort { @Override - public boolean getHumidity(String key) { + public String getHumidity() { - CoapClient client1 = new CoapClient("coap://130.82.171.10:5683/humidity") + CoapClient client1 = new CoapClient("coap://130.82.171.10:5683/humidity"); + String result = null; + try { + result = client1.get().getResponseText(); + } catch (ConnectorException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return result; } } diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java index b865cfd..d2cda18 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/application/port/out/GetHumidityPort.java @@ -1,5 +1,9 @@ package ch.unisg.executorhumidity.executor.application.port.out; +import org.eclipse.californium.elements.exception.ConnectorException; + +import java.io.IOException; + public interface GetHumidityPort { - boolean getHumidity(String key); + String getHumidity(); } diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java index 2a8cd3c..703881f 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java @@ -2,11 +2,17 @@ package ch.unisg.executorhumidity.executor.domain; import ch.unisg.executorbase.executor.domain.ExecutorBase; import ch.unisg.executorbase.executor.domain.ExecutorType; +import ch.unisg.executorhumidity.executor.adapter.out.GetHumidityAdapter; +import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import org.eclipse.californium.elements.exception.ConnectorException; + +import java.io.IOException; public class Executor extends ExecutorBase{ - private static final Executor executor = new Exec(ExecutorType.HUMIDITY); + private static final Executor executor = new Executor(ExecutorType.HUMIDITY); // TODO: Add the necessary ports + private final GetHumidityPort getHumidityPort = new GetHumidityAdapter(); private Executor(ExecutorType executorType) {super(executorType);} @@ -18,5 +24,9 @@ public class Executor extends ExecutorBase{ protected String execution(String input) { //TODO: Fill + + String result = getHumidityPort.getHumidity(); + + return result; } } diff --git a/executor-robot/pom.xml b/executor-robot/pom.xml index ca95edf..67fe35b 100644 --- a/executor-robot/pom.xml +++ b/executor-robot/pom.xml @@ -45,7 +45,37 @@ executor-base 0.0.1-SNAPSHOT - + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + + ch.unisg + executor-base + 0.0.1-SNAPSHOT + compile + + -- 2.45.1 From bcb8130f78e4e0437cac9676d7281130b6bb3588 Mon Sep 17 00:00:00 2001 From: rahimiankeanu Date: Sun, 12 Dec 2021 16:49:03 +0100 Subject: [PATCH 03/12] Renaming task type --- .../ch/unisg/executorBase/executor/domain/ExecutorType.java | 2 +- .../ch/unisg/executorcomputation/executor/domain/Executor.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java index ca9533a..33ae142 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorType.java @@ -1,7 +1,7 @@ package ch.unisg.executorbase.executor.domain; public enum ExecutorType { - ADDITION, ROBOT; + COMPUTATION, ROBOT; /** * Checks if the give executor type exists. diff --git a/executor-computation/src/main/java/ch/unisg/executorcomputation/executor/domain/Executor.java b/executor-computation/src/main/java/ch/unisg/executorcomputation/executor/domain/Executor.java index 582b57f..2da59db 100644 --- a/executor-computation/src/main/java/ch/unisg/executorcomputation/executor/domain/Executor.java +++ b/executor-computation/src/main/java/ch/unisg/executorcomputation/executor/domain/Executor.java @@ -7,7 +7,7 @@ import ch.unisg.executorbase.executor.domain.ExecutorType; public class Executor extends ExecutorBase { - private static final Executor executor = new Executor(ExecutorType.ADDITION); + private static final Executor executor = new Executor(ExecutorType.COMPUTATION); public static Executor getExecutor() { return executor; -- 2.45.1 From 7a66f375566fe8f2682404fdd0bfd8792c0b707b Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 12 Dec 2021 19:41:41 +0100 Subject: [PATCH 04/12] WebSub fixes --- .../tapas/TapasAuctionHouseApplication.java | 30 ++++---- .../common/clients/WebSubSubscriber.java | 70 +++++++++++-------- ...tionStartedEventListenerWebSubAdapter.java | 5 +- .../websub/DiscoverWebSubAdapter.java | 33 +++++++++ .../websub/ValidateIntentWebSubAdapter.java | 18 +---- ...PublishAuctionStartedEventMqttAdapter.java | 1 - ...blishAuctionStartedEventWebSubAdapter.java | 13 +--- .../domain/AuctionHouseDiscovery.java | 7 +- .../src/main/resources/application.properties | 6 +- 9 files changed, 106 insertions(+), 77 deletions(-) create mode 100644 tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java index 6aa001d..5504e4f 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java @@ -3,20 +3,18 @@ package ch.unisg.tapas; import ch.unisg.tapas.auctionhouse.adapter.common.clients.TapasMqttClient; import ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt.AuctionEventsMqttDispatcher; import ch.unisg.tapas.auctionhouse.domain.AuctionHouseDiscovery; +import ch.unisg.tapas.auctionhouse.domain.AuctionHouseDiscoveryInformation; import ch.unisg.tapas.auctionhouse.adapter.common.clients.WebSubSubscriber; import ch.unisg.tapas.common.AuctionHouseResourceDirectory; -import ch.unisg.tapas.common.ConfigProperties; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.paho.client.mqttv3.MqttException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import java.net.URI; -import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -28,23 +26,17 @@ import java.util.concurrent.TimeUnit; public class TapasAuctionHouseApplication { private static final Logger LOGGER = LogManager.getLogger(TapasAuctionHouseApplication.class); - public static String RESOURCE_DIRECTORY = "http://localhost:3500"; public static String DEFAULT_MQTT_BROKER = "tcp://broker.hivemq.com:1883"; private static ConfigurableEnvironment ENVIRONMENT; - public static void main(String[] args) { SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class); ENVIRONMENT = tapasAuctioneerApp.run(args).getEnvironment(); - // TODO Set start up of message services with config // We will use these bootstrap methods in Week 6: bootstrapMarketplaceWithWebSub(); - bootstrapMarketplaceWithMqtt(); - - ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); - executor.scheduleAtFixedRate(crawlerRunnable, 30, 30, TimeUnit.SECONDS); + // bootstrapMarketplaceWithMqtt() } /** * Discovers auction houses and subscribes to WebSub notifications @@ -52,11 +44,12 @@ public class TapasAuctionHouseApplication { private static void bootstrapMarketplaceWithWebSub() { discoverAuctionHouseEndpoints(); - // WebSubSubscriber subscriber = new WebSubSubscriber(); + WebSubSubscriber subscriber = new WebSubSubscriber(ENVIRONMENT.getProperty("auctionhouse.uri")); - // for (String endpoint : auctionHouseEndpoints) { - // subscriber.subscribeToAuctionHouseEndpoint(URI.create(endpoint)); - // } + for (AuctionHouseDiscoveryInformation endpoint : AuctionHouseDiscovery.getInstance().getAuctionHouseDiscoveryList()) { + subscriber.subscribeToAuctionHouseEndpoint(endpoint.getWebSubUri().getValue()); + } + //subscriber.subscribeToAuctionHouseEndpoint("https://websub.rocks/blog/100/v7wVgkzRrZXTadY3pXjx"); } /** @@ -83,17 +76,20 @@ public class TapasAuctionHouseApplication { private static void discoverAuctionHouseEndpoints() { AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( - URI.create(RESOURCE_DIRECTORY) + URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) ); AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); + + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + executor.scheduleAtFixedRate(crawlerRunnable, 300, 300, TimeUnit.SECONDS); } private static Runnable crawlerRunnable = new Runnable() { public void run() { AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( - URI.create(RESOURCE_DIRECTORY) + URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) ); AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java index 5b3fc32..bd0ffb9 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java @@ -2,9 +2,11 @@ package ch.unisg.tapas.auctionhouse.adapter.common.clients; 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.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -18,22 +20,23 @@ import org.springframework.http.HttpStatus; */ public class WebSubSubscriber { - // TODO get this somehow from properties file. But on clue how to do this with static variables - static String WEBSUB_HUB_ENDPOINT = "http://localhost:3000"; - static String AUCTION_HOUSE_ENDPOINT = "http://localhost:8086"; - Logger logger = Logger.getLogger(WebSubSubscriber.class.getName()); - public void subscribeToAuctionHouseEndpoint(URI endpoint) { - // TODO decide with other groups about auction house endpoint uri to discover websub topics - // and replace the hardcoded one with it - String topic = discoverWebSubTopic("http://localhost:3100/websub"); + String AUCTION_HOUSE_ENDPOINT; - if (topic == null) { + public WebSubSubscriber(String AUCTION_HOUSE_ENDPOINT) { + this.AUCTION_HOUSE_ENDPOINT = AUCTION_HOUSE_ENDPOINT; + } + + public void subscribeToAuctionHouseEndpoint(URI endpoint) { + + HashMap links = discoverWebSubTopic(endpoint); + + if (links.isEmpty()) { return; } - subscribeToWebSub(topic); + subscribeToWebSub(links.get("hub"), links.get("self")); // Shoudl be done :D // TODO Subscribe to the auction house endpoint via WebSub: @@ -52,23 +55,30 @@ public class WebSubSubscriber { // - the implementation notes of the WebSub hub you are using to distribute events } - private String discoverWebSubTopic(String endpoint) { + private HashMap discoverWebSubTopic(URI endpoint) { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(endpoint)) + .uri(endpoint) .header("Content-Type", "application/json") .GET() .build(); + HashMap links = new HashMap<>(); try { HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == HttpStatus.OK.value()) { - // TODO decide with other groups about response structure and replace the hardcoded - // uri with response uri - JSONObject jsonObject = new JSONObject(response.body()); - System.out.println(jsonObject); - return jsonObject.getString("topic"); + for (String link : response.headers().allValues("link")) { + if (link.contains("rel=\"hub\"")) { + String hub = link.split(">")[0]; + links.put("hub", hub.substring(1)); + } else if(link.contains("rel=\"self\"")) { + String self = link.split(">")[0]; + links.put("self", self.substring(1)); + } + System.out.println(link); + } + // TODO check for HTML tags second if links are not present in headers } else { logger.log(Level.SEVERE, "Could not find a websub uri"); } @@ -78,24 +88,26 @@ public class WebSubSubscriber { } catch (IOException e) { logger.log(Level.SEVERE, e.getLocalizedMessage(), e); } - return null; + return links; } - private void subscribeToWebSub(String topic) { + private void subscribeToWebSub(String hub, String topic) { HttpClient client = HttpClient.newHttpClient(); - String body = new JSONObject() - .put("hub.callback", AUCTION_HOUSE_ENDPOINT + "/auction-started") - .put("hub.mode", "subscribe") - .put("hub.topic", topic) - .put("hub.ws", false) - .toString(); - + URI hubURI; + try { + hubURI = new URI(hub); + } catch (URISyntaxException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(WEBSUB_HUB_ENDPOINT)) - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(body)) + .uri(hubURI) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString("hub.mode=subscribe&hub.callback=" + AUCTION_HOUSE_ENDPOINT + + "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c" + "&hub.topic=" + topic)) .build(); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java index 4f67dad..cec11b3 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java @@ -34,9 +34,12 @@ public class AuctionStartedEventListenerWebSubAdapter { * @return 200 OK * @throws URISyntaxException **/ - @PostMapping(path = "/auction-started") + // TODO generate a new capability ID instead of using a hardcoded one. + @PostMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c") public ResponseEntity handleExecutorAddedEvent(@RequestBody Collection payload) throws URISyntaxException { + System.out.println("new auctions :O"); + for (AuctionJsonRepresentation auction : payload) { auctionStartedHandler.handleAuctionStartedEvent( new AuctionStartedEvent( diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java new file mode 100644 index 0000000..0aea2c6 --- /dev/null +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java @@ -0,0 +1,33 @@ +package ch.unisg.tapas.auctionhouse.adapter.in.messaging.websub; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +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 DiscoverWebSubAdapter { + + @Value("${websub.hub.uri}") + private String webSubHubUri; + + @Value("${auctionhouse.uri}") + private String auctionHouseUri; + + /** + * Controller which listens to auction-started callbacks + * @return 200 OK + **/ + @GetMapping(path = "/websub/auctions") + public ResponseEntity handleDiscoverWebSubAuction() { + + HttpHeaders header = new HttpHeaders(); + header.add("link", "<" + auctionHouseUri + "/auctions/>; rel=\"self\""); + header.add("link", "<" + webSubHubUri + ">; rel=\"hub\""); + + return ResponseEntity.ok().headers(header).body(""); + } +} diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/ValidateIntentWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/ValidateIntentWebSubAdapter.java index 7bfb450..e3a9da9 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/ValidateIntentWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/ValidateIntentWebSubAdapter.java @@ -13,21 +13,9 @@ import org.springframework.web.bind.annotation.*; @RestController public class ValidateIntentWebSubAdapter { - @Value("${application.environment}") - private String environment; - - @GetMapping(path = "/auction-started") + // TODO generate a new capability ID instead of using a hardcoded one. + @GetMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c") public ResponseEntity validateIntent(@RequestParam("hub.challenge") String challenge) { - // Different implementation depending on local development or production - if (environment.equalsIgnoreCase("development")) { - HttpHeaders headers = new HttpHeaders(); - headers.add("Content-Type", "application/json"); - String body = new JSONObject() - .put("hub.challenge", challenge) - .toString(); - return new ResponseEntity<>(body, headers, HttpStatus.OK); - } else { - return new ResponseEntity<>(challenge, HttpStatus.OK); - } + return new ResponseEntity<>(challenge, HttpStatus.OK); } } diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java index a041b4f..6cf39ce 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java @@ -15,7 +15,6 @@ import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component -@Primary public class PublishAuctionStartedEventMqttAdapter implements AuctionStartedEventPort { private static final Logger LOGGER = LogManager.getLogger(PublishAuctionStartedEventMqttAdapter.class); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java index 228f43b..140fade 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java @@ -29,12 +29,8 @@ import java.util.stream.Collectors; * This class is a template for publishing auction started events via WebSub. */ @Component +@Primary public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEventPort { - // You can use this object to retrieve properties from application.properties, e.g. the - // WebSub hub publish endpoint, etc. - @Autowired - private ConfigProperties config; - @Value("${auctionhouse.uri}") private String auctionHouseUri; @@ -47,15 +43,12 @@ public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEv public void publishAuctionStartedEvent(AuctionStartedEvent event) { HttpClient client = HttpClient.newHttpClient(); - String body = new JSONObject() - .put("hub.url", auctionHouseUri + "/auctions") - .put("hub.mode", "publish") - .toString(); + String body = "hub.url=" + auctionHouseUri + "/auctions/&hub.mode=publish"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(webSubHubUri)) - .header("Content-Type", "application/json") + .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java index 5088ff1..da3ff55 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java @@ -20,6 +20,9 @@ public class AuctionHouseDiscovery { } }; + // TODO load from config + static String AUCTION_HOUSE_URI = "http://localhost:8086"; + @Getter private List auctionHouseDiscoveryList = new ArrayList<>() { }; @@ -28,8 +31,8 @@ public class AuctionHouseDiscovery { try { // Add our information to list auctionHouseDiscoveryList.add(new AuctionHouseDiscoveryInformation( - new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI("http://localhost:8086")), - new AuctionHouseDiscoveryInformation.WebSubUri(new URI("http://localhost:8086/websub")), + new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI(AUCTION_HOUSE_URI)), + new AuctionHouseDiscoveryInformation.WebSubUri(new URI(AUCTION_HOUSE_URI + "/websub/auctions")), new AuctionHouseDiscoveryInformation.TaskTypes(tasktypes), new AuctionHouseDiscoveryInformation.TimeStamp(new Timestamp(new Date().getTime())), new AuctionHouseDiscoveryInformation.GroupName("Group 1") diff --git a/tapas-auction-house/src/main/resources/application.properties b/tapas-auction-house/src/main/resources/application.properties index dd9735d..56da8b5 100644 --- a/tapas-auction-house/src/main/resources/application.properties +++ b/tapas-auction-house/src/main/resources/application.properties @@ -10,6 +10,8 @@ auction.house.uri=https://tapas-auction-house.86-119-35-40.nip.io tasks.list.uri=http://localhost:8081 application.environment=development -auctionhouse.uri=http://localhost:8086 -websub.hub.uri=http://localhost:3000 +auctionhouse.uri=http://fe10-77-59-152-182.eu.ngrok.io +websub.hub.uri=https://pubsubhubbub.appspot.com mqtt.broker.uri=tcp://localhost:1883 + +discovery.endpoint.uri=http://localhost:3500/discovery/ -- 2.45.1 From 4593e5bddb62fce33cacc3dd73cc9bd910624f44 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 12 Dec 2021 20:24:04 +0100 Subject: [PATCH 05/12] uri updates --- .deployment/docker-compose.yml | 2 ++ .../ch/unisg/tapas/TapasAuctionHouseApplication.java | 2 +- .../in/messaging/websub/DiscoverWebSubAdapter.java | 2 +- .../PublishAuctionStartedEventWebSubAdapter.java | 12 +----------- .../src/main/resources/application.properties | 1 - 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.deployment/docker-compose.yml b/.deployment/docker-compose.yml index ebe2b67..c6f1955 100644 --- a/.deployment/docker-compose.yml +++ b/.deployment/docker-compose.yml @@ -67,6 +67,8 @@ services: - ./:/data/ environment: mqtt.broker.uri: tcp://broker.hivemq.com:1883 + discovery.endpoint.uri: https://tapas-auction-house.86.119.35.213.nip.io/discovery/ + auction.house.uri: https://tapas-auction-house.86-119-35-40.nip.io labels: - "traefik.enable=true" - "traefik.http.routers.tapas-auction-house.rule=Host(`tapas-auction-house.${PUB_IP}.nip.io`)" diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java index 5504e4f..103e3d6 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java @@ -44,7 +44,7 @@ public class TapasAuctionHouseApplication { private static void bootstrapMarketplaceWithWebSub() { discoverAuctionHouseEndpoints(); - WebSubSubscriber subscriber = new WebSubSubscriber(ENVIRONMENT.getProperty("auctionhouse.uri")); + WebSubSubscriber subscriber = new WebSubSubscriber(ENVIRONMENT.getProperty("auction.house.uri")); for (AuctionHouseDiscoveryInformation endpoint : AuctionHouseDiscovery.getInstance().getAuctionHouseDiscoveryList()) { subscriber.subscribeToAuctionHouseEndpoint(endpoint.getWebSubUri().getValue()); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java index 0aea2c6..332d13e 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java @@ -14,7 +14,7 @@ public class DiscoverWebSubAdapter { @Value("${websub.hub.uri}") private String webSubHubUri; - @Value("${auctionhouse.uri}") + @Value("${auction.house.uri}") private String auctionHouseUri; /** diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java index 140fade..4a0be21 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java @@ -1,29 +1,19 @@ package ch.unisg.tapas.auctionhouse.adapter.out.messaging.websub; import ch.unisg.tapas.auctionhouse.application.port.out.AuctionStartedEventPort; -import ch.unisg.tapas.auctionhouse.domain.Auction; import ch.unisg.tapas.auctionhouse.domain.AuctionStartedEvent; -import ch.unisg.tapas.common.ConfigProperties; -import org.json.JSONObject; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.URI; -import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; /** * This class is a template for publishing auction started events via WebSub. @@ -31,7 +21,7 @@ import java.util.stream.Collectors; @Component @Primary public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEventPort { - @Value("${auctionhouse.uri}") + @Value("${auction.house.uri}") private String auctionHouseUri; @Value("${websub.hub.uri}") diff --git a/tapas-auction-house/src/main/resources/application.properties b/tapas-auction-house/src/main/resources/application.properties index 56da8b5..7de99a6 100644 --- a/tapas-auction-house/src/main/resources/application.properties +++ b/tapas-auction-house/src/main/resources/application.properties @@ -10,7 +10,6 @@ auction.house.uri=https://tapas-auction-house.86-119-35-40.nip.io tasks.list.uri=http://localhost:8081 application.environment=development -auctionhouse.uri=http://fe10-77-59-152-182.eu.ngrok.io websub.hub.uri=https://pubsubhubbub.appspot.com mqtt.broker.uri=tcp://localhost:1883 -- 2.45.1 From 13b02aa115e2c2a224fb4989df8177db1444b833 Mon Sep 17 00:00:00 2001 From: rahimiankeanu Date: Sun, 12 Dec 2021 20:26:14 +0100 Subject: [PATCH 06/12] Roster requests auction when an internal executor is missing --- .../adapter/in/web/NewTaskController.java | 2 +- .../out/web/LaunchAuctionEventAdapter.java | 58 +++++++++++++++++++ .../application/port/in/NewTaskCommand.java | 8 ++- .../port/out/LaunchAuctionEventPort.java | 8 +++ .../application/service/NewTaskService.java | 9 ++- .../ch/unisg/roster/roster/domain/Task.java | 9 +++ .../domain/event/LaunchAuctionEvent.java | 14 +++++ 7 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java create mode 100644 roster/src/main/java/ch/unisg/roster/roster/application/port/out/LaunchAuctionEventPort.java create mode 100644 roster/src/main/java/ch/unisg/roster/roster/domain/event/LaunchAuctionEvent.java diff --git a/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/NewTaskController.java b/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/NewTaskController.java index 7ff5349..e153322 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/NewTaskController.java +++ b/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/NewTaskController.java @@ -31,7 +31,7 @@ public class NewTaskController { logger.info("New task with id:" + task.getTaskID()); - NewTaskCommand command = new NewTaskCommand(task.getTaskID(), task.getTaskType(), + NewTaskCommand command = new NewTaskCommand(task.getTaskID(), task.getTaskUri(), task.getTaskType(), task.getInputData()); boolean success = newTaskUseCase.addNewTaskToQueue(command); diff --git a/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java b/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java new file mode 100644 index 0000000..77bf619 --- /dev/null +++ b/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java @@ -0,0 +1,58 @@ +package ch.unisg.roster.roster.adapter.out.web; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.HashMap; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.beans.factory.annotation.Value; + +import ch.unisg.roster.roster.application.port.out.LaunchAuctionEventPort; +import ch.unisg.roster.roster.domain.event.LaunchAuctionEvent; + +public class LaunchAuctionEventAdapter implements LaunchAuctionEventPort { + + @Value("${auction.house.uri}") + String server; + + @Override + public void launchAuctionEvent(LaunchAuctionEvent launchAuctionEvent) { + + var values = new HashMap() {{ + + put("taskUri", launchAuctionEvent.taskUri); + put("taskType", launchAuctionEvent.taskType.getValue()); + + }}; + + var objectMapper = new ObjectMapper(); + String requestBody = null; + try { + requestBody = objectMapper.writeValueAsString(values); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(server+"/auctions/")) + .header("Content-Type", "application/task+json") + .POST(HttpRequest.BodyPublishers.ofString(requestBody)) + .build(); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + +} diff --git a/roster/src/main/java/ch/unisg/roster/roster/application/port/in/NewTaskCommand.java b/roster/src/main/java/ch/unisg/roster/roster/application/port/in/NewTaskCommand.java index 5db2b9f..f312518 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/application/port/in/NewTaskCommand.java +++ b/roster/src/main/java/ch/unisg/roster/roster/application/port/in/NewTaskCommand.java @@ -1,5 +1,7 @@ package ch.unisg.roster.roster.application.port.in; +import java.net.URI; + import javax.validation.constraints.NotNull; import ch.unisg.roster.roster.domain.valueobject.ExecutorType; @@ -20,8 +22,12 @@ public class NewTaskCommand extends SelfValidating { @NotNull private final String inputData; - public NewTaskCommand(String taskID, ExecutorType taskType, String inputData) { + @NotNull + private final String taskUri; + + public NewTaskCommand(String taskID, String taskUri, ExecutorType taskType, String inputData) { this.taskID = taskID; + this.taskUri = taskUri; this.taskType = taskType; this.inputData = inputData; this.validateSelf(); diff --git a/roster/src/main/java/ch/unisg/roster/roster/application/port/out/LaunchAuctionEventPort.java b/roster/src/main/java/ch/unisg/roster/roster/application/port/out/LaunchAuctionEventPort.java new file mode 100644 index 0000000..dd828f4 --- /dev/null +++ b/roster/src/main/java/ch/unisg/roster/roster/application/port/out/LaunchAuctionEventPort.java @@ -0,0 +1,8 @@ +package ch.unisg.roster.roster.application.port.out; + +import ch.unisg.roster.roster.domain.event.LaunchAuctionEvent; + +public interface LaunchAuctionEventPort { + + void launchAuctionEvent(LaunchAuctionEvent launchAuctionEvent); +} diff --git a/roster/src/main/java/ch/unisg/roster/roster/application/service/NewTaskService.java b/roster/src/main/java/ch/unisg/roster/roster/application/service/NewTaskService.java index c1aab5c..84cae57 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/application/service/NewTaskService.java +++ b/roster/src/main/java/ch/unisg/roster/roster/application/service/NewTaskService.java @@ -6,10 +6,12 @@ import org.springframework.stereotype.Component; import ch.unisg.roster.roster.application.port.in.NewTaskCommand; import ch.unisg.roster.roster.application.port.in.NewTaskUseCase; +import ch.unisg.roster.roster.application.port.out.LaunchAuctionEventPort; import ch.unisg.roster.roster.application.port.out.NewTaskEventPort; import ch.unisg.roster.roster.domain.ExecutorRegistry; import ch.unisg.roster.roster.domain.Roster; import ch.unisg.roster.roster.domain.Task; +import ch.unisg.roster.roster.domain.event.LaunchAuctionEvent; import ch.unisg.roster.roster.domain.event.NewTaskEvent; import lombok.RequiredArgsConstructor; @@ -20,6 +22,8 @@ public class NewTaskService implements NewTaskUseCase { private final NewTaskEventPort newTaskEventPort; + private final LaunchAuctionEventPort launchAuctionEventPort; + /** * Checks if we can execute the give task, if yes the task gets added to the task queue and return true. * If the task can not be executed by an internal or auction house executor, the method return false. @@ -31,7 +35,10 @@ public class NewTaskService implements NewTaskUseCase { ExecutorRegistry executorRegistry = ExecutorRegistry.getInstance(); if (!executorRegistry.containsTaskType(command.getTaskType())) { - return false; + LaunchAuctionEvent launchAuctionEvent = new LaunchAuctionEvent( command.getTaskUri(), + command.getTaskType()); + launchAuctionEventPort.launchAuctionEvent(launchAuctionEvent); + return true; } Task task = new Task(command.getTaskID(), command.getTaskType(), command.getInputData()); diff --git a/roster/src/main/java/ch/unisg/roster/roster/domain/Task.java b/roster/src/main/java/ch/unisg/roster/roster/domain/Task.java index ee30763..25cfcc0 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/domain/Task.java +++ b/roster/src/main/java/ch/unisg/roster/roster/domain/Task.java @@ -12,6 +12,9 @@ public class Task { @Getter private ExecutorType taskType; + @Getter + private String taskUri; + @Getter @Setter private String inputData; @@ -40,6 +43,12 @@ public class Task { this.inputData = inputData; } + public Task(String taskID, String taskUri, ExecutorType taskType) { + this.taskID = taskID; + this.taskUri = taskUri; + this.taskType = taskType; + } + public Task() {} } diff --git a/roster/src/main/java/ch/unisg/roster/roster/domain/event/LaunchAuctionEvent.java b/roster/src/main/java/ch/unisg/roster/roster/domain/event/LaunchAuctionEvent.java new file mode 100644 index 0000000..e68f823 --- /dev/null +++ b/roster/src/main/java/ch/unisg/roster/roster/domain/event/LaunchAuctionEvent.java @@ -0,0 +1,14 @@ +package ch.unisg.roster.roster.domain.event; + +import ch.unisg.roster.roster.domain.valueobject.ExecutorType; + +public class LaunchAuctionEvent { + public final String taskUri; + public final ExecutorType taskType; + + public LaunchAuctionEvent(String taskUri, ExecutorType taskType) { + this.taskUri = taskUri; + this.taskType = taskType; + } + +} -- 2.45.1 From 99e60f656c3ffd6d5199400694d1a69dbe3f8bdb Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 12 Dec 2021 20:40:22 +0100 Subject: [PATCH 07/12] small bugfixes --- .../executor/application/service/NotifyExecutorPoolService.java | 2 +- .../ch/unisg/executorBase/executor/domain/ExecutorBase.java | 2 +- .../executor/adapter/in/web/TaskAvailableController.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java index 64b6d23..aee3142 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/application/service/NotifyExecutorPoolService.java @@ -1,4 +1,4 @@ -package ch.unisg.executorBase.executor.application.service; +package ch.unisg.executorbase.executor.application.service; import ch.unisg.common.valueobject.ExecutorURI; import ch.unisg.executorbase.executor.application.port.out.NotifyExecutorPoolPort; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java index 5f125f2..50acce0 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java @@ -89,6 +89,6 @@ public abstract class ExecutorBase { * Implementation of the actual execution method of an executor * @return the execution result **/ - protected abstract String execution(String input) throws ConnectorException, IOException, ConnectorException; + protected abstract String execution(String input); } diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java index be85ab8..b66472c 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/in/web/TaskAvailableController.java @@ -27,7 +27,7 @@ public class TaskAvailableController { if (ExecutorType.contains(taskType.toUpperCase())) { TaskAvailableCommand command = new TaskAvailableCommand( ExecutorType.valueOf(taskType.toUpperCase())); - CompletableFuture.runAsync(() -> taskAvailableUseCase.newTaskAvailable(command); + CompletableFuture.runAsync(() -> taskAvailableUseCase.newTaskAvailable(command)); } // Add the content type as a response header -- 2.45.1 From b1b94336b29f3d3181722966ef2a9528afc2dd88 Mon Sep 17 00:00:00 2001 From: "julius.lautz" Date: Tue, 14 Dec 2021 21:13:49 +0100 Subject: [PATCH 08/12] added td discovery for humidity and robot executor --- .../in/web/TaskAvailableController.java | 2 +- .../web/ExecutionFinishedEventAdapter.java | 2 +- .../executor/domain/ExecutorBase.java | 2 +- executor-humidity/pom.xml | 40 ++++++++- .../adapter/out/GetHumidityAdapter.java | 60 +++++++++++-- .../executor/domain/Executor.java | 3 +- executor-robot/pom.xml | 12 +++ .../out/DeleteUserFromRobotAdapter.java | 10 +-- .../out/InstructionToRobotAdapter.java | 87 ++++++++++++++++-- .../adapter/out/UserToRobotAdapter.java | 90 +++++++++++++++++-- 10 files changed, 276 insertions(+), 32 deletions(-) diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java index 66ef496..32f3486 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/in/web/TaskAvailableController.java @@ -1,4 +1,4 @@ -package ch.unisg.executorbase.executor.adapter.in.web; +package ch.unisg.executorBase.executor.adapter.in.web; import java.util.logging.Logger; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java index f683b81..5d832db 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/ExecutionFinishedEventAdapter.java @@ -1,4 +1,4 @@ -package ch.unisg.executorbase.executor.adapter.out.web; +package ch.unisg.executorBase.executor.adapter.out.web; import java.io.IOException; import java.net.URI; diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java index 50acce0..be5ddd6 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/domain/ExecutorBase.java @@ -5,7 +5,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import ch.unisg.common.valueobject.ExecutorURI; -import ch.unisg.executorbase.executor.adapter.out.web.ExecutionFinishedEventAdapter; +import ch.unisg.executorBase.executor.adapter.out.web.ExecutionFinishedEventAdapter; import ch.unisg.executorbase.executor.adapter.out.web.GetAssignmentAdapter; import ch.unisg.executorbase.executor.adapter.out.web.NotifyExecutorPoolAdapter; import ch.unisg.executorbase.executor.application.port.out.ExecutionFinishedEventPort; diff --git a/executor-humidity/pom.xml b/executor-humidity/pom.xml index 6828a7d..27ed3b6 100644 --- a/executor-humidity/pom.xml +++ b/executor-humidity/pom.xml @@ -3,10 +3,23 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.example + + org.springframework.boot + spring-boot-starter-parent + 2.5.5 + + + org.unisg executor-humidity 1.0-SNAPSHOT + executor-humidity + Demo project for Spring Boot + + + jitpack.io + https://jitpack.io + + org.springframework.boot @@ -30,6 +43,12 @@ org.eclipse.californium californium-core 3.0.0 + compile + + + com.github.Interactions-HSG + wot-td-java + 0.1.1 @@ -38,4 +57,21 @@ 16 + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java index 5cf9c88..c73e356 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/adapter/out/GetHumidityAdapter.java @@ -1,12 +1,26 @@ package ch.unisg.executorhumidity.executor.adapter.out; import ch.unisg.executorhumidity.executor.application.port.out.GetHumidityPort; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.affordances.PropertyAffordance; +import ch.unisg.ics.interactions.wot.td.clients.TDCoapRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDCoapResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.elements.exception.ConnectorException; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Map; +import java.util.Optional; @Component @@ -16,17 +30,49 @@ public class GetHumidityAdapter implements GetHumidityPort { @Override public String getHumidity() { - CoapClient client1 = new CoapClient("coap://130.82.171.10:5683/humidity"); + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/sparql-query") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); - String result = null; try { - result = client1.get().getResponseText(); - } catch (ConnectorException e) { - e.printStackTrace(); + String description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + Optional humidity = td.getPropertyByName("humidity"); + + if (humidity.isPresent()) { + Optional
form = humidity.get().getFirstFormForOperationType(TD.readProperty); + + if (form.isPresent()) { + TDCoapRequest request = new TDCoapRequest(form.get(), TD.readProperty); + try { + TDCoapResponse response = request.execute(); + + Map payload = response.getPayloadAsObject((ObjectSchema) humidity.get().getDataSchema()); + Object result = payload.get("https://interactions.ics.unisg.ch/mirogate#HumidityValue"); + return result.toString(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } catch (IOException e) { e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); } - - return result; + return null; } } diff --git a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java index 703881f..ac73e65 100644 --- a/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java +++ b/executor-humidity/src/main/java/ch/unisg/executorhumidity/executor/domain/Executor.java @@ -11,9 +11,8 @@ import java.io.IOException; public class Executor extends ExecutorBase{ private static final Executor executor = new Executor(ExecutorType.HUMIDITY); - // TODO: Add the necessary ports - private final GetHumidityPort getHumidityPort = new GetHumidityAdapter(); + private final GetHumidityPort getHumidityPort = new GetHumidityAdapter(); private Executor(ExecutorType executorType) {super(executorType);} diff --git a/executor-robot/pom.xml b/executor-robot/pom.xml index 67fe35b..570bd18 100644 --- a/executor-robot/pom.xml +++ b/executor-robot/pom.xml @@ -18,6 +18,12 @@ scs-asse-fs21-group1 https://sonarcloud.io + + + jitpack.io + https://jitpack.io + + org.springframework.boot @@ -75,6 +81,12 @@ 0.0.1-SNAPSHOT compile + + com.github.Interactions-HSG + wot-td-java + 0.1.1 + compile + diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java index 157bc3e..37b605a 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/DeleteUserFromRobotAdapter.java @@ -17,16 +17,16 @@ public class DeleteUserFromRobotAdapter implements DeleteUserFromRobotPort { @Override public boolean deleteUserFromRobot(String key) { - String url = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/user/" + key; - + String url = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.4/user/" + key; + var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .DELETE() .build(); - + var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -38,5 +38,5 @@ public class DeleteUserFromRobotAdapter implements DeleteUserFromRobotPort { } return false; } - + } diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java index c7507e4..531b5eb 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/InstructionToRobotAdapter.java @@ -4,7 +4,21 @@ 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.Map; +import java.util.Optional; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.ActionAffordance; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.DataSchema; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.schemas.StringSchema; +import ch.unisg.ics.interactions.wot.td.security.APIKeySecurityScheme; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -16,9 +30,70 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { @Override public boolean instructionToRobot(String key) { - + + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); + + try { + var description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + // Create the payload to be sent with the Http request + Map elbowPayload = new HashMap<>(); + elbowPayload.put("http://www.w3.org/2001/XMLSchema#int", 400); + + // Get the affordance "setElbow" from the TD + Optional action = td.getActionByName("setElbow"); + + // Get the first form + if (action.isPresent()) { + Optional form = action.get().getFirstForm(); + + // Retrieve the input data schema from the action affordance + Optional inputSchema = action.get().getInputSchema(); + + // If a form is found, use it to create and execute the Http request + if (form.isPresent()) { + TDHttpRequest request = new TDHttpRequest(form.get(), TD.invokeAction); + + if (inputSchema.isPresent()) { + request.setObjectPayload((ObjectSchema) inputSchema.get(), elbowPayload); + + try { + TDHttpResponse response = request.execute(); + System.out.println("Received response with status code: " + response.getStatusCode()); + return true; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return false; + + + + + /* String putEndpoint = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/elbow"; - + String inputJson = "{ \"value\": 400}"; var request = HttpRequest.newBuilder() .uri(URI.create(putEndpoint)) @@ -26,9 +101,9 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { .header("X-API-KEY", key) .PUT(HttpRequest.BodyPublishers.ofString(inputJson)) .build(); - + var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -40,7 +115,7 @@ public class InstructionToRobotAdapter implements InstructionToRobotPort { e.printStackTrace(); } return false; - + */ } - + } diff --git a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java index 92ca8c1..7c20616 100644 --- a/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java +++ b/executor-robot/src/main/java/ch/unisg/executorrobot/executor/adapter/out/UserToRobotAdapter.java @@ -4,7 +4,20 @@ 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.Map; +import java.util.Optional; +import ch.unisg.ics.interactions.wot.td.ThingDescription; +import ch.unisg.ics.interactions.wot.td.affordances.ActionAffordance; +import ch.unisg.ics.interactions.wot.td.affordances.Form; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpRequest; +import ch.unisg.ics.interactions.wot.td.clients.TDHttpResponse; +import ch.unisg.ics.interactions.wot.td.io.TDGraphReader; +import ch.unisg.ics.interactions.wot.td.schemas.DataSchema; +import ch.unisg.ics.interactions.wot.td.schemas.ObjectSchema; +import ch.unisg.ics.interactions.wot.td.vocabularies.TD; +import org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @@ -16,17 +29,77 @@ public class UserToRobotAdapter implements UserToRobotPort { @Override public String userToRobot() { - String postEndpoint = "https://api.interactions.ics.unisg.ch/leubot1/v1.3.0/user"; - + + String endpoint = "https://api.interactions.ics.unisg.ch/search/searchEngine"; + + String input = "@prefix dct: . select ?title where { ?title dct:title 'Mirogate' }"; + + var httpRequest = HttpRequest.newBuilder() + .uri(URI.create(endpoint)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(input)) + .build(); + + var client = HttpClient.newHttpClient(); + + try { + var description = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()).body(); + + // Parse a TD from a string + ThingDescription td = TDGraphReader.readFromString(ThingDescription.TDFormat.RDF_TURTLE, description); + + // Create the payload to be sent with the HTTP request + Map logInPayload = new HashMap<>(); + logInPayload.put("http://xmlns.com/foaf/0.1/Name", "keanu rahimian"); + logInPayload.put("http://xmlns.com/foaf/0.1/Mbox", "keanu.rahimian@student.unisg.ch"); + + // Get the affordance "Log-In" from the TD + Optional action = td.getActionByName("logIn"); + + // Get the first form + if (action.isPresent()) { + Optional form = action.get().getFirstForm(); + + // Retrieve the input data schema from the action affordance + Optional inputSchema = action.get().getInputSchema(); + + // If a form is found, use it to create and execute the HTTP request + if (form.isPresent()) { + TDHttpRequest request = new TDHttpRequest(form.get(), TD.invokeAction); + + if (inputSchema.isPresent()) { + request.setObjectPayload((ObjectSchema) inputSchema.get(), logInPayload); + + try { + TDHttpResponse response = request.execute(); + System.out.println("Received response with status code: " + response.getStatusCode()); + + // TODO: Get the key from the response and return it + // Not exactly sure how to get the headers from the payload, as we need them + // to get the key + + return null; + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + /* String inputJson = "{ \"name\":\"keanu rahimian\", \"email\":\"keanu.rahimian@student.unisg.ch\"}"; var request = HttpRequest.newBuilder() .uri(URI.create(postEndpoint)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(inputJson)) .build(); - - var client = HttpClient.newHttpClient(); - + try { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); @@ -40,7 +113,10 @@ public class UserToRobotAdapter implements UserToRobotPort { e.printStackTrace(); } return null; - + */ + + + return null; } - + } -- 2.45.1 From 467d7aa01577dcc2ecf5202fea8e67774d3466bd Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 14 Dec 2021 21:59:24 +0100 Subject: [PATCH 09/12] updates --- docker-compose.yaml | 24 ++--- .../adapter/out/web/GetAssignmentAdapter.java | 8 +- .../ExecutorcomputationApplication.java | 2 +- .../src/main/resources/application.properties | 3 +- .../ch/unisg/roster/RosterApplication.java | 2 +- .../src/main/resources/application.properties | 3 +- .../tapas/TapasAuctionHouseApplication.java | 49 +++++---- .../common/clients/WebSubSubscriber.java | 2 - .../formats/AuctionJsonRepresentation.java | 28 ++++++ ...tionStartedEventListenerWebSubAdapter.java | 99 ++++++++++++++++--- .../websub/DiscoverWebSubAdapter.java | 2 +- ...PublishAuctionStartedEventMqttAdapter.java | 1 + ...blishAuctionStartedEventWebSubAdapter.java | 2 + .../out/web/AuctionWonEventHttpAdapter.java | 1 + .../domain/AuctionHouseDiscovery.java | 6 +- .../src/main/resources/application.properties | 5 +- 16 files changed, 178 insertions(+), 59 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index c53981f..8566c1b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -72,15 +72,15 @@ services: volumes: - ./executor-computation/src:/opt/app/src - ./executor-computation/target:/opt/app/target - executor-robot: - container_name: executor-robot - build: - context: "." - dockerfile: "./executor-robot/Dockerfile" - target: development - ports: - - "8084:8084" - - "5009:5005" - volumes: - - ./executor-robot/src:/opt/app/src - - ./executor-robot/target:/opt/app/target + # executor-robot: + # container_name: executor-robot + # build: + # context: "." + # dockerfile: "./executor-robot/Dockerfile" + # target: development + # ports: + # - "8084:8084" + # - "5009:5005" + # volumes: + # - ./executor-robot/src:/opt/app/src + # - ./executor-robot/target:/opt/app/target diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java index 4df08dd..5981121 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java @@ -10,6 +10,7 @@ import java.util.logging.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import ch.unisg.common.valueobject.ExecutorURI; @@ -49,12 +50,13 @@ public class GetAssignmentAdapter implements GetAssignmentPort { .build(); try { - logger.info("Sending getAssignment Request"); + logger.info("ExecutorBase | Sending getAssignment request"); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - logger.log(Level.INFO, "getAssignment request result:\n {0}", response.body()); - if (response.body().equals("")) { + if (response.statusCode() != HttpStatus.CREATED.value()) { + logger.info("ExecutorBase | No task assigned"); return null; } + logger.info("ExecutorBase | Task assigned"); JSONObject responseBody = new JSONObject(response.body()); String inputData = responseBody.getString("inputData"); diff --git a/executor-computation/src/main/java/ch/unisg/executorcomputation/ExecutorcomputationApplication.java b/executor-computation/src/main/java/ch/unisg/executorcomputation/ExecutorcomputationApplication.java index fe25430..7a22493 100644 --- a/executor-computation/src/main/java/ch/unisg/executorcomputation/ExecutorcomputationApplication.java +++ b/executor-computation/src/main/java/ch/unisg/executorcomputation/ExecutorcomputationApplication.java @@ -13,7 +13,7 @@ public class ExecutorcomputationApplication { public static void main(String[] args) { try { - TimeUnit.SECONDS.sleep(40); + TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/executor-pool/src/main/resources/application.properties b/executor-pool/src/main/resources/application.properties index c8f67f1..20953a7 100644 --- a/executor-pool/src/main/resources/application.properties +++ b/executor-pool/src/main/resources/application.properties @@ -1,6 +1,7 @@ server.port=8083 -mqtt.broker.uri=tcp://localhost:1883 +# mqtt.broker.uri=tcp://localhost:1883 +mqtt.broker.uri=tcp://broker.hivemq.com spring.data.mongodb.uri=mongodb://root:password@localhost:27017 spring.data.mongodb.database=tapas-executors diff --git a/roster/src/main/java/ch/unisg/roster/RosterApplication.java b/roster/src/main/java/ch/unisg/roster/RosterApplication.java index 973e8f1..7f31c91 100644 --- a/roster/src/main/java/ch/unisg/roster/RosterApplication.java +++ b/roster/src/main/java/ch/unisg/roster/RosterApplication.java @@ -33,7 +33,7 @@ public class RosterApplication { SpringApplication rosterApp = new SpringApplication(RosterApplication.class); ENVIRONMENT = rosterApp.run(args).getEnvironment(); bootstrapMarketplaceWithMqtt(); - initialiseRoster(); + // initialiseRoster(); } /** diff --git a/roster/src/main/resources/application.properties b/roster/src/main/resources/application.properties index ea6544a..d7c1dcb 100644 --- a/roster/src/main/resources/application.properties +++ b/roster/src/main/resources/application.properties @@ -2,7 +2,8 @@ server.port=8082 executor.robot.uri=http://127.0.0.1:8084 executor.computation.uri=http://127.0.0.1:8085 task.list.uri=http://127.0.0.1:8081 -mqtt.broker.uri=tcp://localhost:1883 +# mqtt.broker.uri=tcp://localhost:1883 +mqtt.broker.uri=tcp://broker.hivemq.com spring.data.mongodb.uri=mongodb://root:password@localhost:27017/ spring.data.mongodb.database=tapas-roster diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java index 103e3d6..1d72579 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/TapasAuctionHouseApplication.java @@ -15,6 +15,7 @@ import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import java.net.URI; +import java.net.URISyntaxException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -36,20 +37,25 @@ public class TapasAuctionHouseApplication { // TODO Set start up of message services with config // We will use these bootstrap methods in Week 6: bootstrapMarketplaceWithWebSub(); - // bootstrapMarketplaceWithMqtt() + //bootstrapMarketplaceWithMqtt(); } /** * Discovers auction houses and subscribes to WebSub notifications */ private static void bootstrapMarketplaceWithWebSub() { - discoverAuctionHouseEndpoints(); + // discoverAuctionHouseEndpoints(); WebSubSubscriber subscriber = new WebSubSubscriber(ENVIRONMENT.getProperty("auction.house.uri")); - for (AuctionHouseDiscoveryInformation endpoint : AuctionHouseDiscovery.getInstance().getAuctionHouseDiscoveryList()) { - subscriber.subscribeToAuctionHouseEndpoint(endpoint.getWebSubUri().getValue()); + // for (AuctionHouseDiscoveryInformation endpoint : AuctionHouseDiscovery.getInstance().getAuctionHouseDiscoveryList()) { + // 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(); } - //subscriber.subscribeToAuctionHouseEndpoint("https://websub.rocks/blog/100/v7wVgkzRrZXTadY3pXjx"); } /** @@ -74,25 +80,26 @@ public class TapasAuctionHouseApplication { } } - private static void discoverAuctionHouseEndpoints() { - AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( - URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) - ); + // private static void discoverAuctionHouseEndpoints() { - AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); + // AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( + // URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) + // ); - ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); - executor.scheduleAtFixedRate(crawlerRunnable, 300, 300, TimeUnit.SECONDS); - } + // AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); + + // ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + // executor.scheduleAtFixedRate(crawlerRunnable, 300, 300, TimeUnit.SECONDS); + // } - private static Runnable crawlerRunnable = new Runnable() { - public void run() { - AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( - URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) - ); + // private static Runnable crawlerRunnable = new Runnable() { + // public void run() { + // AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( + // URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri")) + // ); - AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); - } - }; + // AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); + // } + // }; } diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java index bd0ffb9..ea74603 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/clients/WebSubSubscriber.java @@ -38,8 +38,6 @@ public class WebSubSubscriber { subscribeToWebSub(links.get("hub"), links.get("self")); - // Shoudl be done :D - // TODO Subscribe to the auction house endpoint via WebSub: // 1. Send a request to the auction house in order to discover the WebSub hub to subscribe to. // The request URI should depend on the design of the Auction House HTTP API. // 2. Send a subscription request to the discovered WebSub hub to subscribe to events relevant diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/AuctionJsonRepresentation.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/AuctionJsonRepresentation.java index 757c8c8..3004755 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/AuctionJsonRepresentation.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/AuctionJsonRepresentation.java @@ -3,12 +3,16 @@ package ch.unisg.tapas.auctionhouse.adapter.common.formats; import ch.unisg.tapas.auctionhouse.domain.Auction; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; import lombok.Setter; +import java.net.URI; import java.sql.Timestamp; +import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Date; /** * Used to expose a representation of the state of an auction through an interface. This class is @@ -60,4 +64,28 @@ public class AuctionJsonRepresentation { mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); return mapper.writeValueAsString(representation); } + + public static Auction deserialize(String auctionJson) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(auctionJson); + Auction.AuctionId auctionId = new Auction.AuctionId(jsonNode.get("auctionId").asText()); + Auction.AuctionHouseUri auctionHouseUri = new Auction.AuctionHouseUri(URI.create(jsonNode.get("auctionHouseUri").asText())); + Auction.AuctionedTaskUri taskUri = new Auction.AuctionedTaskUri(URI.create(jsonNode.get("taskUri").asText())); + Auction.AuctionedTaskType taskType = new Auction.AuctionedTaskType(jsonNode.get("taskType").asText()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date parsedDate; + try { + parsedDate = dateFormat.parse(jsonNode.get("deadline").toString()); + Timestamp timestamp = new java.sql.Timestamp(parsedDate.getTime()); + Auction.AuctionDeadline deadline = new Auction.AuctionDeadline(timestamp); + + Auction auction = new Auction(auctionId, auctionHouseUri, taskUri, taskType, deadline); + return auction; + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + + } } diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java index cec11b3..520e0a5 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/AuctionStartedEventListenerWebSubAdapter.java @@ -1,20 +1,31 @@ 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.*; @@ -36,20 +47,86 @@ public class AuctionStartedEventListenerWebSubAdapter { **/ // TODO generate a new capability ID instead of using a hardcoded one. @PostMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c") - public ResponseEntity handleExecutorAddedEvent(@RequestBody Collection payload) throws URISyntaxException { + public ResponseEntity handleExecutorAddedEvent(@RequestBody String payload) throws URISyntaxException { System.out.println("new auctions :O"); + System.out.println(payload); - for (AuctionJsonRepresentation auction : payload) { - auctionStartedHandler.handleAuctionStartedEvent( - new AuctionStartedEvent( - new Auction(new AuctionId(auction.getAuctionId()), - new AuctionHouseUri(new URI(auction.getAuctionHouseUri())), - new AuctionedTaskUri(new URI(auction.getTaskUri())), - new AuctionedTaskType(auction.getTaskType()), - new AuctionDeadline(auction.getDeadline())) - )); - } + + JSONArray auctions = new JSONArray(payload); + if (auctions.length() > 0) { + JSONObject auction = auctions.getJSONObject(0); + System.out.print(auction); + // try { + // System.out.println(auction.getString("deadline")); + // System.out.println(AuctionJsonRepresentation.deserialize(auction.toString())); + + // auctionStartedHandler.handleAuctionStartedEvent( + // new AuctionStartedEvent(AuctionJsonRepresentation.deserialize(auction.toString()))); + // } catch (JsonProcessingException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + + + // String auctionHouseURI = "https://tapas-auction-house.86-119-35-40.nip.io/"; + String auctionHouseURI = "http://b311-130-82-247-153.eu.ngrok.io"; + + // String taskListURI = "https://tapas-tasks.86-119-35-40.nip.io"; + String taskListURI = "http://c64f-130-82-247-153.ngrok.io"; + + // TODO Sanitize URIs + String auctionId = auction.getString("auctionId"); + String auctionHouseUri = auction.getString("auctionHouseUri"); + String taskUri = auction.getString("taskUri"); + String taskType = auction.getString("taskType"); + String deadline = auction.getString("deadline"); + + 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(); + } + + + //LOGGER.info(postResponse.statusCode()); + }; + + // for (JSONObject auction : auctions) { + // auctionStartedHandler.handleAuctionStartedEvent( + // new AuctionStartedEvent( + // new Auction(new AuctionId(auction.getAuctionId()), + // new AuctionHouseUri(new URI(auction.getAuctionHouseUri())), + // new AuctionedTaskUri(new URI(auction.getTaskUri())), + // new AuctionedTaskType(auction.getTaskType()), + // new AuctionDeadline(auction.getDeadline())) + // )); + // } return new ResponseEntity<>(HttpStatus.OK); } diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java index 332d13e..f279c43 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/websub/DiscoverWebSubAdapter.java @@ -18,7 +18,7 @@ public class DiscoverWebSubAdapter { private String auctionHouseUri; /** - * Controller which listens to auction-started callbacks + * Controller to discover our websub topic * @return 200 OK **/ @GetMapping(path = "/websub/auctions") diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java index 6cf39ce..4472519 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java @@ -15,6 +15,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component +// @Primary public class PublishAuctionStartedEventMqttAdapter implements AuctionStartedEventPort { private static final Logger LOGGER = LogManager.getLogger(PublishAuctionStartedEventMqttAdapter.class); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java index 4a0be21..02aeb75 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventWebSubAdapter.java @@ -35,6 +35,7 @@ public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEv String body = "hub.url=" + auctionHouseUri + "/auctions/&hub.mode=publish"; + logger.info("Auctions updated:" + body); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(webSubHubUri)) @@ -45,6 +46,7 @@ public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEv try { client.send(request, HttpResponse.BodyHandlers.ofString()); + logger.info("WEBSUB send successfuly"); } catch (InterruptedException e) { logger.log(Level.SEVERE, e.getLocalizedMessage(), e); Thread.currentThread().interrupt(); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/web/AuctionWonEventHttpAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/web/AuctionWonEventHttpAdapter.java index ec04b2b..066a246 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/web/AuctionWonEventHttpAdapter.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/web/AuctionWonEventHttpAdapter.java @@ -43,6 +43,7 @@ public class AuctionWonEventHttpAdapter implements AuctionWonEventPort { .uri(auction.get().getTaskUri().getValue()) .GET() .build(); + var response = client.send(request, HttpResponse.BodyHandlers.ofString()); LOGGER.info(response.body()); JSONObject responseBody = new JSONObject(response.body()); diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java index da3ff55..c234b64 100644 --- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java +++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/AuctionHouseDiscovery.java @@ -21,7 +21,7 @@ public class AuctionHouseDiscovery { }; // TODO load from config - static String AUCTION_HOUSE_URI = "http://localhost:8086"; + // static String AUCTION_HOUSE_URI = "http://localhost:8086"; @Getter private List auctionHouseDiscoveryList = new ArrayList<>() { @@ -31,8 +31,8 @@ public class AuctionHouseDiscovery { try { // Add our information to list auctionHouseDiscoveryList.add(new AuctionHouseDiscoveryInformation( - new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI(AUCTION_HOUSE_URI)), - new AuctionHouseDiscoveryInformation.WebSubUri(new URI(AUCTION_HOUSE_URI + "/websub/auctions")), + new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI("http://localhost:8086")), + new AuctionHouseDiscoveryInformation.WebSubUri(new URI("http://localhost:8086/websub/auctions")), new AuctionHouseDiscoveryInformation.TaskTypes(tasktypes), new AuctionHouseDiscoveryInformation.TimeStamp(new Timestamp(new Date().getTime())), new AuctionHouseDiscoveryInformation.GroupName("Group 1") diff --git a/tapas-auction-house/src/main/resources/application.properties b/tapas-auction-house/src/main/resources/application.properties index 7de99a6..3546905 100644 --- a/tapas-auction-house/src/main/resources/application.properties +++ b/tapas-auction-house/src/main/resources/application.properties @@ -11,6 +11,7 @@ tasks.list.uri=http://localhost:8081 application.environment=development websub.hub.uri=https://pubsubhubbub.appspot.com -mqtt.broker.uri=tcp://localhost:1883 +mqtt.broker.uri=tcp://broker.hivemq.com +# mqtt.broker.uri=tcp://localhost:1883 -discovery.endpoint.uri=http://localhost:3500/discovery/ +discovery.endpoint.uri=http://localhost:3500 -- 2.45.1 From 45edd76c8b048462b580c9bf9631d594350e01ff Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 14 Dec 2021 22:00:32 +0100 Subject: [PATCH 10/12] executorbase bugfixes --- .../executor/adapter/out/web/GetAssignmentAdapter.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java index 4df08dd..5981121 100644 --- a/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java +++ b/executor-base/src/main/java/ch/unisg/executorBase/executor/adapter/out/web/GetAssignmentAdapter.java @@ -10,6 +10,7 @@ import java.util.logging.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import ch.unisg.common.valueobject.ExecutorURI; @@ -49,12 +50,13 @@ public class GetAssignmentAdapter implements GetAssignmentPort { .build(); try { - logger.info("Sending getAssignment Request"); + logger.info("ExecutorBase | Sending getAssignment request"); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - logger.log(Level.INFO, "getAssignment request result:\n {0}", response.body()); - if (response.body().equals("")) { + if (response.statusCode() != HttpStatus.CREATED.value()) { + logger.info("ExecutorBase | No task assigned"); return null; } + logger.info("ExecutorBase | Task assigned"); JSONObject responseBody = new JSONObject(response.body()); String inputData = responseBody.getString("inputData"); -- 2.45.1 From 69b5949f715b26d76c493a2b6953dd0f3d9f1a80 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 14 Dec 2021 22:19:32 +0100 Subject: [PATCH 11/12] roster bugfixes --- .deployment/docker-compose.yml | 1 + .../roster/adapter/out/web/LaunchAuctionEventAdapter.java | 8 ++++++-- roster/src/main/resources/application.properties | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.deployment/docker-compose.yml b/.deployment/docker-compose.yml index ebe2b67..c4796da 100644 --- a/.deployment/docker-compose.yml +++ b/.deployment/docker-compose.yml @@ -86,6 +86,7 @@ services: - ./:/data/ environment: task.list.uri: http://tapas-tasks:8081 + auction.house.uri: http://tapas-auction-house:8086 executor.robot.uri: http://executor-robot:8084 executor.computation.uri: http://executor-computation:8085 mqtt.broker.uri: tcp://broker.hivemq.com:1883 diff --git a/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java b/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java index 77bf619..f6972ac 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java +++ b/roster/src/main/java/ch/unisg/roster/roster/adapter/out/web/LaunchAuctionEventAdapter.java @@ -11,10 +11,14 @@ 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; +import org.springframework.stereotype.Component; import ch.unisg.roster.roster.application.port.out.LaunchAuctionEventPort; import ch.unisg.roster.roster.domain.event.LaunchAuctionEvent; +@Component +@Primary public class LaunchAuctionEventAdapter implements LaunchAuctionEventPort { @Value("${auction.house.uri}") @@ -27,7 +31,7 @@ public class LaunchAuctionEventAdapter implements LaunchAuctionEventPort { put("taskUri", launchAuctionEvent.taskUri); put("taskType", launchAuctionEvent.taskType.getValue()); - + }}; var objectMapper = new ObjectMapper(); @@ -54,5 +58,5 @@ public class LaunchAuctionEventAdapter implements LaunchAuctionEventPort { } } - + } diff --git a/roster/src/main/resources/application.properties b/roster/src/main/resources/application.properties index ea6544a..3edf4b5 100644 --- a/roster/src/main/resources/application.properties +++ b/roster/src/main/resources/application.properties @@ -1,6 +1,7 @@ server.port=8082 executor.robot.uri=http://127.0.0.1:8084 executor.computation.uri=http://127.0.0.1:8085 +auction.house.uri=http://127.0.0.1:8086 task.list.uri=http://127.0.0.1:8081 mqtt.broker.uri=tcp://localhost:1883 -- 2.45.1 From 3e141e5318e441fd0ece5a8ebbb1e7248cabdc4a Mon Sep 17 00:00:00 2001 From: reynisson Date: Tue, 14 Dec 2021 23:46:07 +0100 Subject: [PATCH 12/12] Implemented the remove task workflow. Still got one todo for the workflow that I want to discuss --- .../adapter/in/web/DeleteTaskController.java | 7 +++--- .../port/in/DeleteTaskCommand.java | 6 +---- .../service/DeleteTaskService.java | 2 +- .../ch/unisg/roster/roster/domain/Roster.java | 9 +++++-- .../roster/roster/domain/RosterTest.java | 6 ++--- .../in/web/DeleteTaskWebController.java | 2 ++ .../out/web/CanTaskBeDeletedWebAdapter.java | 25 ++++++------------- .../port/out/CanTaskBeDeletedPort.java | 2 +- .../service/DeleteTaskService.java | 16 ++++++++---- 9 files changed, 37 insertions(+), 38 deletions(-) diff --git a/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/DeleteTaskController.java b/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/DeleteTaskController.java index eef8b71..182fb36 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/DeleteTaskController.java +++ b/roster/src/main/java/ch/unisg/roster/roster/adapter/in/web/DeleteTaskController.java @@ -3,6 +3,7 @@ package ch.unisg.roster.roster.adapter.in.web; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -22,10 +23,10 @@ public class DeleteTaskController { * Controller to delete a task * @return 200 OK, 409 Conflict **/ - @DeleteMapping(path = "/task", consumes = {"application/task+json"}) - public ResponseEntity applyForTask(@RequestBody Task task) { + @DeleteMapping(path = "/task/{taskId}") + public ResponseEntity deleteTask(@PathVariable("taskId") String taskId) { - DeleteTaskCommand command = new DeleteTaskCommand(task.getTaskID(), task.getTaskType()); + DeleteTaskCommand command = new DeleteTaskCommand(taskId); if (deleteTaskUseCase.deleteTask(command)) { return new ResponseEntity<>(HttpStatus.OK); diff --git a/roster/src/main/java/ch/unisg/roster/roster/application/port/in/DeleteTaskCommand.java b/roster/src/main/java/ch/unisg/roster/roster/application/port/in/DeleteTaskCommand.java index 9f59dc3..503428e 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/application/port/in/DeleteTaskCommand.java +++ b/roster/src/main/java/ch/unisg/roster/roster/application/port/in/DeleteTaskCommand.java @@ -13,12 +13,8 @@ public class DeleteTaskCommand extends SelfValidating { @NotNull private final String taskId; - @NotNull - private final ExecutorType taskType; - - public DeleteTaskCommand(String taskId, ExecutorType taskType) { + public DeleteTaskCommand(String taskId) { this.taskId = taskId; - this.taskType = taskType; this.validateSelf(); } } diff --git a/roster/src/main/java/ch/unisg/roster/roster/application/service/DeleteTaskService.java b/roster/src/main/java/ch/unisg/roster/roster/application/service/DeleteTaskService.java index a6b4841..69036e5 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/application/service/DeleteTaskService.java +++ b/roster/src/main/java/ch/unisg/roster/roster/application/service/DeleteTaskService.java @@ -21,7 +21,7 @@ public class DeleteTaskService implements DeleteTaskUseCase { @Override public boolean deleteTask(DeleteTaskCommand command) { Roster roster = Roster.getInstance(); - return roster.deleteTask(command.getTaskId(), command.getTaskType()); + return roster.deleteTask(command.getTaskId()); } } diff --git a/roster/src/main/java/ch/unisg/roster/roster/domain/Roster.java b/roster/src/main/java/ch/unisg/roster/roster/domain/Roster.java index 3893566..1153caa 100644 --- a/roster/src/main/java/ch/unisg/roster/roster/domain/Roster.java +++ b/roster/src/main/java/ch/unisg/roster/roster/domain/Roster.java @@ -76,9 +76,14 @@ public class Roster { * Deletes a task if it is still in the queue. * @return Whether the task got deleted or not **/ - public boolean deleteTask(String taskID, ExecutorType taskType) { + public boolean deleteTask(String taskID) { logger.log(Level.INFO, "Try to delete task with id {0}", taskID); - return queues.get(taskType.getValue()).removeIf(task -> task.getTaskID().equalsIgnoreCase(taskID)); + for(var listOfTasks : queues.entrySet()){ + if(listOfTasks.getValue().removeIf(task -> task.getTaskID().equals(taskID))){ + return true; + } + } + return false; } public void initialiseRoster(List rosterItemList){ diff --git a/roster/src/test/java/ch/unisg/roster/roster/domain/RosterTest.java b/roster/src/test/java/ch/unisg/roster/roster/domain/RosterTest.java index 7fd1081..d2e62e6 100644 --- a/roster/src/test/java/ch/unisg/roster/roster/domain/RosterTest.java +++ b/roster/src/test/java/ch/unisg/roster/roster/domain/RosterTest.java @@ -31,7 +31,7 @@ public class RosterTest { assertThat(task.getTaskType().getValue().toString()).isEqualTo("TEST-TYPE"); assertThat(task.getTaskID()).isEqualTo("TEST-ID"); - boolean empty_queue = roster.deleteTask("TEST-ID", new ExecutorType("TEST-TYPE")); + 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); @@ -44,8 +44,8 @@ public class RosterTest { queues.clear(); roster.addTaskToQueue(new Task("TEST-ID", "TEST-TYPE")); - boolean test = roster.deleteTask("TEST-ID", new ExecutorType("TEST-TYPE")); - + boolean test = roster.deleteTask("TEST-ID"); + // TODO Fix assert for queue assertThat(test).isEqualTo(true); assertThat(queues.size()).isEqualTo(1); } diff --git a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/in/web/DeleteTaskWebController.java b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/in/web/DeleteTaskWebController.java index ef79e6a..11c2442 100644 --- a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/in/web/DeleteTaskWebController.java +++ b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/in/web/DeleteTaskWebController.java @@ -25,6 +25,7 @@ public class DeleteTaskWebController { this.deleteClassUseCase = deleteClassUseCase; } + // TODO change to DELETE and why are we using task URI here? @PostMapping(path="/tasks/deleteTask", consumes = {TaskJsonRepresentation.MEDIA_TYPE}) public ResponseEntity deleteTask (@RequestBody Task task){ try { @@ -35,6 +36,7 @@ public class DeleteTaskWebController { // Check if the task with the given identifier exists if (deleteATask.isEmpty()) { // If not, through a 404 Not Found status code + // TODO is 404 the best here? throw new ResponseStatusException(HttpStatus.NOT_FOUND); } diff --git a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/out/web/CanTaskBeDeletedWebAdapter.java b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/out/web/CanTaskBeDeletedWebAdapter.java index a69f2e5..2b5c495 100644 --- a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/out/web/CanTaskBeDeletedWebAdapter.java +++ b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/adapter/out/web/CanTaskBeDeletedWebAdapter.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import java.io.IOException; @@ -25,36 +26,24 @@ public class CanTaskBeDeletedWebAdapter implements CanTaskBeDeletedPort { String server; @Override - public void canTaskBeDeletedEvent(DeleteTaskEvent event){ - - var values = new HashMap<> () {{ - put("taskId", event.taskId); - put("taskUri", event.taskUri); - }}; - - var objectMapper = new ObjectMapper(); - String requestBody = null; - try { - requestBody = objectMapper.writeValueAsString(values); - } catch (JsonProcessingException e){ - e.printStackTrace(); - } - + 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")) + .uri(URI.create(server+"$/task/" + event.taskId)) .header("Content-Type", "application/task+json") - .POST(HttpRequest.BodyPublishers.ofString(requestBody)) + .DELETE() .build(); - //Todo: The following parameters probably need to be changed to get the right error code try { HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + return response.statusCode() == HttpStatus.OK.value(); } catch (IOException e){ e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } + + return false; } } diff --git a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/port/out/CanTaskBeDeletedPort.java b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/port/out/CanTaskBeDeletedPort.java index 67bde16..5a0707f 100644 --- a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/port/out/CanTaskBeDeletedPort.java +++ b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/port/out/CanTaskBeDeletedPort.java @@ -3,5 +3,5 @@ package ch.unisg.tapastasks.tasks.application.port.out; import ch.unisg.tapastasks.tasks.domain.DeleteTaskEvent; public interface CanTaskBeDeletedPort { - void canTaskBeDeletedEvent(DeleteTaskEvent event); + boolean canTaskBeDeletedEvent(DeleteTaskEvent event); } diff --git a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/service/DeleteTaskService.java b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/service/DeleteTaskService.java index 35685a3..c3d392c 100644 --- a/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/service/DeleteTaskService.java +++ b/tapas-tasks/src/main/java/ch/unisg/tapastasks/tasks/application/service/DeleteTaskService.java @@ -3,6 +3,8 @@ package ch.unisg.tapastasks.tasks.application.service; import ch.unisg.tapastasks.tasks.application.port.in.DeleteTaskCommand; import ch.unisg.tapastasks.tasks.application.port.in.DeleteTaskUseCase; +import ch.unisg.tapastasks.tasks.application.port.out.CanTaskBeDeletedPort; +import ch.unisg.tapastasks.tasks.domain.DeleteTaskEvent; import ch.unisg.tapastasks.tasks.domain.Task; import ch.unisg.tapastasks.tasks.domain.TaskList; import jdk.jshell.spi.ExecutionControl; @@ -17,17 +19,21 @@ import java.util.Optional; @Transactional public class DeleteTaskService implements DeleteTaskUseCase { + private final CanTaskBeDeletedPort canTaskBeDeletedPort; + @Override public Optional deleteTask(DeleteTaskCommand command){ TaskList taskList = TaskList.getTapasTaskList(); Optional updatedTask = taskList.retrieveTaskById(command.getTaskId()); - Task newTask = updatedTask.get(); - // TODO: Fill in the right condition into the if-statement and the else-statement - if (true){ - return taskList.deleteTaskById(command.getTaskId()); + + if(updatedTask.isPresent() && updatedTask.get().getTaskStatus().getValue().equals(Task.Status.OPEN)){ + // If task exists, and it is open then we try deleting it from the roster + if(canTaskBeDeletedPort.canTaskBeDeletedEvent(new DeleteTaskEvent(command.getTaskId().getValue(), command.getTaskUri().getValue()))){ + return taskList.deleteTaskById(command.getTaskId()); + } } - // TODO Handle with a return message + return Optional.empty(); } } -- 2.45.1