diff --git a/executor-pool/src/main/resources/application.properties b/executor-pool/src/main/resources/application.properties
index 0c9ba7e..c8fd60a 100644
--- a/executor-pool/src/main/resources/application.properties
+++ b/executor-pool/src/main/resources/application.properties
@@ -1,3 +1,3 @@
server.port=8083
-mqtt.broker.uri=tcp://localhost:1883
+mqtt.broker.uri=tcp://broker.hivemq.com:1883
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 7438032..18c7631 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
@@ -27,7 +27,7 @@ public class TapasAuctionHouseApplication {
private ConfigProperties config;
public static String RESOURCE_DIRECTORY = "https://api.interactions.ics.unisg.ch/auction-houses/";
- public static String MQTT_BROKER = "tcp://localhost:1883";
+ public static String MQTT_BROKER = "tcp://broker.hivemq.com:1883";
public static void main(String[] args) {
SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class);
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 ea4cf2c..757c8c8 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
@@ -8,6 +8,7 @@ import lombok.Getter;
import lombok.Setter;
import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
/**
* Used to expose a representation of the state of an auction through an interface. This class is
@@ -15,7 +16,7 @@ import java.sql.Timestamp;
* to modify this class as you see fit!
*/
public class AuctionJsonRepresentation {
- public static final String MEDIA_TYPE = "application/json";
+ public static final String MEDIA_TYPE = "application/auction+json";
@Getter @Setter
private String auctionId;
@@ -56,7 +57,7 @@ public class AuctionJsonRepresentation {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
-
+ mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
return mapper.writeValueAsString(representation);
}
}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/BidJsonRepresentation.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/BidJsonRepresentation.java
new file mode 100644
index 0000000..7ae3dda
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/BidJsonRepresentation.java
@@ -0,0 +1,43 @@
+package ch.unisg.tapas.auctionhouse.adapter.common.formats;
+
+import ch.unisg.tapas.auctionhouse.domain.Bid;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.text.SimpleDateFormat;
+
+public class BidJsonRepresentation {
+ public static final String MEDIA_TYPE = "application/bid+json";
+
+ @Getter @Setter
+ private String auctionId;
+
+ @Getter @Setter
+ private String bidderName;
+
+ @Getter @Setter
+ private String bidderAuctionHouseUri;
+
+ @Getter @Setter
+ private String bidderTaskListUri;
+
+ public BidJsonRepresentation() {}
+
+ public BidJsonRepresentation(Bid bid){
+ this.auctionId = bid.getAuctionId().getValue();
+ this.bidderName = bid.getBidderName().getValue();
+ this.bidderAuctionHouseUri = bid.getBidderAuctionHouseUri().getValue().toString();
+ this.bidderTaskListUri = bid.getBidderTaskListUri().getValue().toString();
+ }
+
+ public static String serialize(Bid bid) throws JsonProcessingException {
+ BidJsonRepresentation representation = new BidJsonRepresentation(bid);
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ return mapper.writeValueAsString(representation);
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/TaskJsonRepresentation.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/TaskJsonRepresentation.java
new file mode 100644
index 0000000..782978c
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/TaskJsonRepresentation.java
@@ -0,0 +1,124 @@
+package ch.unisg.tapas.auctionhouse.adapter.common.formats;
+
+import ch.unisg.tapas.auctionhouse.domain.Task;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * This class is used to expose and consume representations of tasks through the HTTP interface. The
+ * representations conform to the custom JSON-based media type "application/task+json". The media type
+ * is just an identifier and can be registered with
+ * IANA to promote interoperability.
+ */
+final public class TaskJsonRepresentation {
+ // The media type used for this task representation format
+ public static final String MEDIA_TYPE = "application/task+json";
+
+ // A task identifier specific to our implementation (e.g., a UUID). This identifier is then used
+ // to generate the task's URI. URIs are standard uniform identifiers and use a universal syntax
+ // that can be referenced (and dereferenced) independent of context. In our uniform HTTP API,
+ // we identify tasks via URIs and not implementation-specific identifiers.
+ @Getter @Setter
+ private String taskId;
+
+ // A string that represents the task's name
+ @Getter
+ private final String taskName;
+
+ // A string that identifies the task's type. This string could also be a URI (e.g., defined in some
+ // Web ontology, as we shall see later in the course), but it's not constrained to be a URI.
+ // The task's type can be used to assign executors to tasks, to decide what tasks to bid for, etc.
+ @Getter
+ private final String taskType;
+
+ // The task's status: OPEN, ASSIGNED, RUNNING, or EXECUTED (see Task.Status)
+ @Getter @Setter
+ private String taskStatus;
+
+ // If this task is a delegated task (i.e., a shadow of another task), this URI points to the
+ // original task. Because URIs are standard and uniform, we can just dereference this URI to
+ // retrieve a representation of the original task.
+ @Getter @Setter
+ private String originalTaskUri;
+
+ // The service provider who executes this task. The service provider is a any string that identifies
+ // a TAPAS group (e.g., tapas-group1). This identifier could also be a URI (if we have a good reason
+ // for it), but it's not constrained to be a URI.
+ @Getter @Setter
+ private String serviceProvider;
+
+ // A string that provides domain-specific input data for this task. In the context of this project,
+ // we can parse and interpret the input data based on the task's type.
+ @Getter @Setter
+ private String inputData;
+
+ // A string that provides domain-specific output data for this task. In the context of this project,
+ // we can parse and interpret the output data based on the task's type.
+ @Getter @Setter
+ private String outputData;
+
+ /**
+ * Instantiate a task representation with a task name and type.
+ *
+ * @param taskName string that represents the task's name
+ * @param taskType string that represents the task's type
+ */
+ public TaskJsonRepresentation(String taskName, String taskType) {
+ this.taskName = taskName;
+ this.taskType = taskType;
+
+ this.taskStatus = null;
+ this.originalTaskUri = null;
+ this.serviceProvider = null;
+ this.inputData = null;
+ this.outputData = null;
+ }
+
+ /**
+ * Instantiate a task representation from a domain concept.
+ *
+ * @param task the task
+ */
+ public TaskJsonRepresentation(Task task) {
+ this(task.getTaskName().getValue(), task.getTaskType().getValue());
+
+ this.taskId = task.getTaskId().getValue();
+ this.taskStatus = task.getTaskStatus().getValue().name();
+
+ this.originalTaskUri = (task.getOriginalTaskUri() == null) ?
+ null : task.getOriginalTaskUri().getValue();
+
+ this.serviceProvider = (task.getProvider() == null) ? null : task.getProvider().getValue();
+ this.inputData = (task.getInputData() == null) ? null : task.getInputData().getValue();
+ this.outputData = (task.getOutputData() == null) ? null : task.getOutputData().getValue();
+ }
+
+ /**
+ * Convenience method used to serialize a task provided as a domain concept in the format exposed
+ * through the uniform HTTP API.
+ *
+ * @param task the task as defined in the domain
+ * @return a string serialization using the JSON-based representation format defined for tasks
+ * @throws JsonProcessingException if a runtime exception occurs during object serialization
+ */
+ public static String serialize(Task task) throws JsonProcessingException {
+ TaskJsonRepresentation representation = new TaskJsonRepresentation(task);
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ return mapper.writeValueAsString(representation);
+ }
+
+ public String serialize() throws JsonProcessingException {
+ TaskJsonRepresentation representation = this;
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ return mapper.writeValueAsString(representation);
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/AuctionEventsMqttDispatcher.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/AuctionEventsMqttDispatcher.java
index 7d30453..91872f2 100644
--- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/AuctionEventsMqttDispatcher.java
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/AuctionEventsMqttDispatcher.java
@@ -28,6 +28,7 @@ public class AuctionEventsMqttDispatcher {
private void initRouter() {
router.put("ch/unisg/tapas/executors/added", new ExecutorAddedEventListenerMqttAdapter());
router.put("ch/unisg/tapas/executors/removed", new ExecutorRemovedEventListenerMqttAdapter());
+ router.put("ch/unisg/tapas/auctions", new ExternalAuctionStartedEventListenerMqttAdapter());
}
/**
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/BidReceivedEventListenerMqttAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/BidReceivedEventListenerMqttAdapter.java
new file mode 100644
index 0000000..29f45da
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/BidReceivedEventListenerMqttAdapter.java
@@ -0,0 +1,52 @@
+package ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt;
+
+import ch.unisg.tapas.auctionhouse.application.handler.BidReceivedHandler;
+import ch.unisg.tapas.auctionhouse.application.handler.ExecutorAddedHandler;
+import ch.unisg.tapas.auctionhouse.application.port.in.ExecutorAddedEvent;
+import ch.unisg.tapas.auctionhouse.domain.Auction;
+import ch.unisg.tapas.auctionhouse.domain.Bid;
+import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEvent;
+import ch.unisg.tapas.auctionhouse.domain.ExecutorRegistry;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+
+import java.net.URI;
+
+public class BidReceivedEventListenerMqttAdapter extends AuctionEventMqttListener {
+ private static final Logger LOGGER = LogManager.getLogger(BidReceivedEventListenerMqttAdapter.class);
+
+ @Override
+ public boolean handleEvent(MqttMessage message){
+ String payload = new String(message.getPayload());
+
+ try {
+ // Note: this message representation is provided only as an example. You should use a
+ // representation that makes sense in the context of your application.
+ JsonNode data = new ObjectMapper().readTree(payload);
+
+ String auctionId = data.get("auctionId").asText();
+ String bidderName = data.get("bidderName").asText();
+ String bidderAuctionHouseUri = data.get("bidderAuctionHouseUri").asText();
+ String bidderTaskListUri = data.get("bidderTaskListUri").asText();
+
+ BidReceivedEvent bidReceivedEvent = new BidReceivedEvent( new Bid(
+ new Auction.AuctionId(auctionId),
+ new Bid.BidderName(bidderName),
+ new Bid.BidderAuctionHouseUri(URI.create(bidderAuctionHouseUri)),
+ new Bid.BidderTaskListUri(URI.create(bidderTaskListUri))
+ ));
+
+ BidReceivedHandler bidReceivedHandler = new BidReceivedHandler();
+ bidReceivedHandler.handleNewBidReceivedEvent(bidReceivedEvent);
+ } catch (JsonProcessingException | NullPointerException e) {
+ LOGGER.error(e.getMessage(), e);
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/ExternalAuctionStartedEventListenerMqttAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/ExternalAuctionStartedEventListenerMqttAdapter.java
new file mode 100644
index 0000000..5e17d96
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/messaging/mqtt/ExternalAuctionStartedEventListenerMqttAdapter.java
@@ -0,0 +1,86 @@
+package ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt;
+
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.TaskJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.application.handler.BidReceivedHandler;
+import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEvent;
+import ch.unisg.tapas.auctionhouse.domain.Auction;
+import ch.unisg.tapas.auctionhouse.domain.Bid;
+import ch.unisg.tapas.auctionhouse.domain.ExecutorRegistry;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.springframework.beans.factory.annotation.Value;
+
+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.sql.Timestamp;
+
+public class ExternalAuctionStartedEventListenerMqttAdapter extends AuctionEventMqttListener{
+ private static final Logger LOGGER = LogManager.getLogger(ExternalAuctionStartedEventListenerMqttAdapter.class);
+
+ @Value("${auction.house.uri}")
+ String auctionHouseURI;
+
+ @Value("${tasks.list.uri}")
+ String taskListURI;
+
+ @Override
+ public boolean handleEvent(MqttMessage message){
+ String payload = new String(message.getPayload());
+
+ try {
+ // Note: this message representation is provided only as an example. You should use a
+ // representation that makes sense in the context of your application.
+ JsonNode data = new ObjectMapper().readTree(payload);
+
+ String auctionId = data.get("auctionId").asText();
+ String auctionHouseUri = data.get("auctionHouseUri").asText();
+ String taskUri = data.get("taskUri").asText();
+ String taskType = data.get("taskType").asText();
+ String deadline = data.get("deadline").asText();
+
+ var capable = ExecutorRegistry.getInstance().containsTaskType(new Auction.AuctionedTaskType(taskType));
+ // TODO check deadline
+ if(capable){
+ 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 = 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());
+
+ LOGGER.info(postResponse.statusCode());
+ }
+ } catch (JsonProcessingException | NullPointerException e) {
+ LOGGER.error(e.getMessage(), e);
+ return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (Exception e){
+ LOGGER.error(e.getMessage(), e);
+ }
+
+ return true;
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/AddBidWebController.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/AddBidWebController.java
new file mode 100644
index 0000000..3431c8d
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/AddBidWebController.java
@@ -0,0 +1,38 @@
+package ch.unisg.tapas.auctionhouse.adapter.in.web;
+
+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.BidReceivedHandler;
+import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEvent;
+import ch.unisg.tapas.auctionhouse.domain.Auction;
+import ch.unisg.tapas.auctionhouse.domain.Bid;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.URI;
+
+// TODO Fix structure due to MQTT
+@RestController
+public class AddBidWebController {
+ @PostMapping(path = "/bid", consumes = BidJsonRepresentation.MEDIA_TYPE)
+ public ResponseEntity addBid(@RequestBody BidJsonRepresentation payload) {
+ BidReceivedEvent bidReceivedEvent = new BidReceivedEvent(new Bid(
+ new Auction.AuctionId(payload.getAuctionId()),
+ new Bid.BidderName(payload.getBidderName()),
+ new Bid.BidderAuctionHouseUri(URI.create(payload.getBidderAuctionHouseUri())),
+ new Bid.BidderTaskListUri(URI.create(payload.getBidderTaskListUri()))
+ ));
+
+ BidReceivedHandler bidReceivedHandler = new BidReceivedHandler();
+ bidReceivedHandler.handleNewBidReceivedEvent(bidReceivedEvent);
+
+ HttpHeaders responseHeaders = new HttpHeaders();
+
+ return new ResponseEntity<>(responseHeaders, HttpStatus.NO_CONTENT);
+ }
+
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/WinningBidWebController.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/WinningBidWebController.java
new file mode 100644
index 0000000..9d252b5
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/in/web/WinningBidWebController.java
@@ -0,0 +1,59 @@
+package ch.unisg.tapas.auctionhouse.adapter.in.web;
+
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.AuctionJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.TaskJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt.ExternalAuctionStartedEventListenerMqttAdapter;
+import ch.unisg.tapas.auctionhouse.domain.Task;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+@RestController
+public class WinningBidWebController {
+ private static final Logger LOGGER = LogManager.getLogger(WinningBidWebController.class);
+
+ @Value("${tasks.list.uri}")
+ String taskListURI;
+
+ @PostMapping(path = "/taskwinner", consumes = TaskJsonRepresentation.MEDIA_TYPE)
+ public ResponseEntity winningBid(@RequestBody TaskJsonRepresentation payload){
+ try {
+ var body = payload.serialize();
+ LOGGER.info(body);
+ var postURI = URI.create(taskListURI + "/tasks/");
+ HttpRequest postRequest = HttpRequest.newBuilder()
+ .uri(postURI)
+ .header("Content-Type", TaskJsonRepresentation.MEDIA_TYPE)
+ .POST(HttpRequest.BodyPublishers.ofString(body))
+ .build();
+
+ HttpClient client = HttpClient.newHttpClient();
+ var postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
+
+ LOGGER.info(postResponse.statusCode());
+
+
+ HttpHeaders responseHeaders = new HttpHeaders();
+ return new ResponseEntity<>(responseHeaders, HttpStatus.NO_CONTENT);
+ }
+ catch (
+ IOException | InterruptedException e) {
+ throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventMqttAdapter.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java
similarity index 95%
rename from tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventMqttAdapter.java
rename to tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java
index d5bb0fc..a041b4f 100644
--- a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/websub/PublishAuctionStartedEventMqttAdapter.java
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/out/messaging/mqtt/PublishAuctionStartedEventMqttAdapter.java
@@ -1,4 +1,4 @@
-package ch.unisg.tapas.auctionhouse.adapter.out.messaging.websub;
+package ch.unisg.tapas.auctionhouse.adapter.out.messaging.mqtt;
import ch.unisg.tapas.auctionhouse.adapter.common.clients.TapasMqttClient;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.AuctionJsonRepresentation;
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 26949f2..4583892 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
@@ -1,10 +1,24 @@
package ch.unisg.tapas.auctionhouse.adapter.out.web;
+import ch.unisg.tapas.auctionhouse.adapter.common.formats.TaskJsonRepresentation;
+import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler;
import ch.unisg.tapas.auctionhouse.application.port.out.AuctionWonEventPort;
+import ch.unisg.tapas.auctionhouse.domain.AuctionRegistry;
import ch.unisg.tapas.auctionhouse.domain.AuctionWonEvent;
+import ch.unisg.tapas.auctionhouse.domain.Task;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Value;
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;
+
/**
* This class is a template for sending auction won events via HTTP. This class was created here only
* as a placeholder, it is up to you to decide how such events should be sent (e.g., via HTTP,
@@ -13,8 +27,54 @@ import org.springframework.stereotype.Component;
@Component
@Primary
public class AuctionWonEventHttpAdapter implements AuctionWonEventPort {
+ private static final Logger LOGGER = LogManager.getLogger(AuctionWonEventHttpAdapter.class);
+
+ @Value("${tasks.list.uri}")
+ String server;
+
@Override
public void publishAuctionWonEvent(AuctionWonEvent event) {
+ try{
+ var auction = AuctionRegistry.getInstance().getAuctionById(event.getWinningBid().getAuctionId());
+
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .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());
+
+ var task = new Task(
+ new Task.TaskName(responseBody.getString("taskName")),
+ new Task.TaskType(responseBody.getString("taskType")),
+ new Task.OriginalTaskUri(auction.get().getTaskUri().getValue().toString()),
+ new Task.TaskStatus(ch.unisg.tapas.auctionhouse.domain.Task.Status.ASSIGNED),
+ new Task.TaskId(responseBody.getString("taskId")),
+ new Task.InputData(responseBody.getString("inputData")),
+ new Task.ServiceProvider("TODO")
+ );
+
+ String body = TaskJsonRepresentation.serialize(task);
+ LOGGER.info(body);
+ var postURI = URI.create(auction.get().getAuctionHouseUri().getValue().toString() + "/taskwinner");
+ HttpRequest postRequest = HttpRequest.newBuilder()
+ .uri(postURI)
+ .header("Content-Type", TaskJsonRepresentation.MEDIA_TYPE)
+ .POST(HttpRequest.BodyPublishers.ofString(body))
+ .build();
+
+ var postResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
+
+ LOGGER.info(postResponse.statusCode());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (Exception e){
+ LOGGER.error(e.getMessage(), e);
+ }
}
}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/handler/BidReceivedHandler.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/handler/BidReceivedHandler.java
new file mode 100644
index 0000000..dc992ac
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/handler/BidReceivedHandler.java
@@ -0,0 +1,17 @@
+package ch.unisg.tapas.auctionhouse.application.handler;
+
+import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEvent;
+import ch.unisg.tapas.auctionhouse.application.port.in.BidReceivedEventHandler;
+import ch.unisg.tapas.auctionhouse.domain.AuctionRegistry;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BidReceivedHandler implements BidReceivedEventHandler {
+ @Override
+ public boolean handleNewBidReceivedEvent(BidReceivedEvent bidReceivedEvent){
+ var auction = AuctionRegistry.getInstance().getAuctionById(bidReceivedEvent.bid.getAuctionId());
+ // TODO Handle if auction not there
+ auction.get().addBid(bidReceivedEvent.bid);
+ return true;
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEvent.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEvent.java
new file mode 100644
index 0000000..560f50b
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEvent.java
@@ -0,0 +1,17 @@
+package ch.unisg.tapas.auctionhouse.application.port.in;
+
+import ch.unisg.tapas.auctionhouse.domain.Bid;
+import ch.unisg.tapas.common.SelfValidating;
+import lombok.Getter;
+
+import javax.validation.constraints.NotNull;
+
+public class BidReceivedEvent extends SelfValidating {
+ @NotNull
+ public Bid bid;
+
+ public BidReceivedEvent(Bid bid){
+ this.bid = bid;
+ validateSelf();
+ }
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEventHandler.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEventHandler.java
new file mode 100644
index 0000000..b17ac6b
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/application/port/in/BidReceivedEventHandler.java
@@ -0,0 +1,5 @@
+package ch.unisg.tapas.auctionhouse.application.port.in;
+
+public interface BidReceivedEventHandler {
+ boolean handleNewBidReceivedEvent(BidReceivedEvent bidReceivedEvent);
+}
diff --git a/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/Task.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/Task.java
new file mode 100644
index 0000000..3fd0d89
--- /dev/null
+++ b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/domain/Task.java
@@ -0,0 +1,122 @@
+package ch.unisg.tapas.auctionhouse.domain;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.Value;
+
+import java.util.UUID;
+
+/**This is a domain entity**/
+public class Task {
+ public enum Status {
+ OPEN, ASSIGNED, RUNNING, EXECUTED
+ }
+
+ @Getter
+ private final TaskId taskId;
+
+ @Getter
+ private final TaskName taskName;
+
+ @Getter
+ private final TaskType taskType;
+
+ @Getter @Setter
+ public TaskStatus taskStatus; // had to make public for CompleteTaskService
+
+ @Getter
+ public TaskResult taskResult; // same as above
+
+ @Getter
+ private final OriginalTaskUri originalTaskUri;
+
+ @Getter @Setter
+ private ServiceProvider provider;
+
+ @Getter @Setter
+ private InputData inputData;
+
+ @Getter @Setter
+ private OutputData outputData;
+
+ public Task(TaskName taskName, TaskType taskType, OriginalTaskUri taskUri) {
+ this.taskName = taskName;
+ this.taskType = taskType;
+ this.taskStatus = new TaskStatus(Status.OPEN);
+ this.taskId = new TaskId(UUID.randomUUID().toString());
+ this.taskResult = new TaskResult("");
+ this.originalTaskUri = taskUri;
+
+ this.inputData = null;
+ this.outputData = null;
+ }
+
+ public Task(TaskName taskName, TaskType taskType, OriginalTaskUri taskUri, TaskStatus taskStatus, TaskId taskId, InputData inputData, ServiceProvider serviceProvider) {
+ this.taskName = taskName;
+ this.taskType = taskType;
+ this.taskStatus = taskStatus;
+ this.taskId = taskId;
+ this.taskResult = new TaskResult("");
+ this.originalTaskUri = taskUri;
+ this.provider = serviceProvider;
+
+ this.inputData = inputData;
+ this.outputData = new OutputData("");
+ }
+
+ protected static Task createTaskWithNameAndType(TaskName name, TaskType type) {
+ //This is a simple debug message to see that the request has reached the right method in the core
+ System.out.println("New Task: " + name.getValue() + " " + type.getValue());
+ return new Task(name, type, null);
+ }
+
+ protected static Task createTaskWithNameAndTypeAndOriginalTaskUri(TaskName name, TaskType type,
+ OriginalTaskUri originalTaskUri) {
+ return new Task(name, type, originalTaskUri);
+ }
+
+ @Value
+ public static class TaskId {
+ String value;
+ }
+
+ @Value
+ public static class TaskName {
+ String value;
+ }
+
+ @Value
+ public static class TaskType {
+ String value;
+ }
+
+ @Value
+ public static class OriginalTaskUri {
+ String value;
+ }
+
+ @Value
+ public static class TaskStatus {
+ Status value;
+ }
+
+ @Value
+ public static class ServiceProvider {
+ String value;
+ }
+
+ @Value
+ public static class InputData {
+ String value;
+ }
+
+ @Value
+ public static class OutputData {
+ String value;
+ }
+
+ @Value
+ public static class TaskResult{
+ private String value;
+ }
+}
diff --git a/tapas-auction-house/src/main/resources/application.properties b/tapas-auction-house/src/main/resources/application.properties
index 706362e..7b94a5a 100644
--- a/tapas-auction-house/src/main/resources/application.properties
+++ b/tapas-auction-house/src/main/resources/application.properties
@@ -5,7 +5,7 @@ websub.hub.publish=https://websub.appspot.com/
group=tapas-group-tutors
auction.house.uri=https://tapas-auction-house.86-119-34-23.nip.io/
-tasks.list.uri=https://tapas-tasks.86-119-34-23.nip.io/
+tasks.list.uri=http://localhost:8081
application.environment=development
auctionhouse.uri=http://localhost:8086