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/TaskJsonRepresentation.java b/tapas-auction-house/src/main/java/ch/unisg/tapas/auctionhouse/adapter/common/formats/TaskJsonRepresentation.java index 467c550..782978c 100644 --- 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 @@ -112,4 +112,13 @@ final public class TaskJsonRepresentation { 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/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/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()); + } + } +}