Merge pull request #105 from SCS-ASSE-FS21-Group1/websub-improvements

Websub improvements
This commit is contained in:
Marcel 2021-12-15 12:11:03 +01:00 committed by GitHub
commit 27ccc54458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 266 additions and 129 deletions

View File

@ -67,6 +67,8 @@ services:
- ./:/data/ - ./:/data/
environment: environment:
mqtt.broker.uri: tcp://broker.hivemq.com:1883 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: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.routers.tapas-auction-house.rule=Host(`tapas-auction-house.${PUB_IP}.nip.io`)" - "traefik.http.routers.tapas-auction-house.rule=Host(`tapas-auction-house.${PUB_IP}.nip.io`)"

View File

@ -72,15 +72,15 @@ services:
volumes: volumes:
- ./executor-computation/src:/opt/app/src - ./executor-computation/src:/opt/app/src
- ./executor-computation/target:/opt/app/target - ./executor-computation/target:/opt/app/target
executor-robot: # executor-robot:
container_name: executor-robot # container_name: executor-robot
build: # build:
context: "." # context: "."
dockerfile: "./executor-robot/Dockerfile" # dockerfile: "./executor-robot/Dockerfile"
target: development # target: development
ports: # ports:
- "8084:8084" # - "8084:8084"
- "5009:5005" # - "5009:5005"
volumes: # volumes:
- ./executor-robot/src:/opt/app/src # - ./executor-robot/src:/opt/app/src
- ./executor-robot/target:/opt/app/target # - ./executor-robot/target:/opt/app/target

View File

@ -13,7 +13,7 @@ public class ExecutorcomputationApplication {
public static void main(String[] args) { public static void main(String[] args) {
try { try {
TimeUnit.SECONDS.sleep(40); TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -1,6 +1,7 @@
server.port=8083 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.uri=mongodb://root:password@localhost:27017
spring.data.mongodb.database=tapas-executors spring.data.mongodb.database=tapas-executors

View File

@ -33,7 +33,7 @@ public class RosterApplication {
SpringApplication rosterApp = new SpringApplication(RosterApplication.class); SpringApplication rosterApp = new SpringApplication(RosterApplication.class);
ENVIRONMENT = rosterApp.run(args).getEnvironment(); ENVIRONMENT = rosterApp.run(args).getEnvironment();
bootstrapMarketplaceWithMqtt(); bootstrapMarketplaceWithMqtt();
initialiseRoster(); // initialiseRoster();
} }
/** /**

View File

@ -3,7 +3,8 @@ executor.robot.uri=http://127.0.0.1:8084
executor.computation.uri=http://127.0.0.1:8085 executor.computation.uri=http://127.0.0.1:8085
auction.house.uri=http://127.0.0.1:8086 auction.house.uri=http://127.0.0.1:8086
task.list.uri=http://127.0.0.1:8081 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.uri=mongodb://root:password@localhost:27017/
spring.data.mongodb.database=tapas-roster spring.data.mongodb.database=tapas-roster

View File

@ -3,20 +3,19 @@ package ch.unisg.tapas;
import ch.unisg.tapas.auctionhouse.adapter.common.clients.TapasMqttClient; import ch.unisg.tapas.auctionhouse.adapter.common.clients.TapasMqttClient;
import ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt.AuctionEventsMqttDispatcher; import ch.unisg.tapas.auctionhouse.adapter.in.messaging.mqtt.AuctionEventsMqttDispatcher;
import ch.unisg.tapas.auctionhouse.domain.AuctionHouseDiscovery; 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.auctionhouse.adapter.common.clients.WebSubSubscriber;
import ch.unisg.tapas.common.AuctionHouseResourceDirectory; import ch.unisg.tapas.common.AuctionHouseResourceDirectory;
import ch.unisg.tapas.common.ConfigProperties;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttException; 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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import java.net.URI; import java.net.URI;
import java.util.List; import java.net.URISyntaxException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -28,35 +27,35 @@ import java.util.concurrent.TimeUnit;
public class TapasAuctionHouseApplication { public class TapasAuctionHouseApplication {
private static final Logger LOGGER = LogManager.getLogger(TapasAuctionHouseApplication.class); 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"; public static String DEFAULT_MQTT_BROKER = "tcp://broker.hivemq.com:1883";
private static ConfigurableEnvironment ENVIRONMENT; private static ConfigurableEnvironment ENVIRONMENT;
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class); SpringApplication tapasAuctioneerApp = new SpringApplication(TapasAuctionHouseApplication.class);
ENVIRONMENT = tapasAuctioneerApp.run(args).getEnvironment(); ENVIRONMENT = tapasAuctioneerApp.run(args).getEnvironment();
// TODO Set start up of message services with config // TODO Set start up of message services with config
// We will use these bootstrap methods in Week 6: // We will use these bootstrap methods in Week 6:
bootstrapMarketplaceWithWebSub(); bootstrapMarketplaceWithWebSub();
bootstrapMarketplaceWithMqtt(); //bootstrapMarketplaceWithMqtt();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(crawlerRunnable, 30, 30, TimeUnit.SECONDS);
} }
/** /**
* Discovers auction houses and subscribes to WebSub notifications * Discovers auction houses and subscribes to WebSub notifications
*/ */
private static void bootstrapMarketplaceWithWebSub() { private static void bootstrapMarketplaceWithWebSub() {
discoverAuctionHouseEndpoints(); // discoverAuctionHouseEndpoints();
// WebSubSubscriber subscriber = new WebSubSubscriber(); WebSubSubscriber subscriber = new WebSubSubscriber(ENVIRONMENT.getProperty("auction.house.uri"));
// for (String endpoint : auctionHouseEndpoints) { // for (AuctionHouseDiscoveryInformation endpoint : AuctionHouseDiscovery.getInstance().getAuctionHouseDiscoveryList()) {
// subscriber.subscribeToAuctionHouseEndpoint(URI.create(endpoint)); // 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();
}
} }
/** /**
@ -81,22 +80,26 @@ public class TapasAuctionHouseApplication {
} }
} }
private static void discoverAuctionHouseEndpoints() { // private static void discoverAuctionHouseEndpoints() {
AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory(
URI.create(RESOURCE_DIRECTORY)
);
AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints()); // AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory(
} // URI.create(ENVIRONMENT.getProperty("discovery.endpoint.uri"))
// );
private static Runnable crawlerRunnable = new Runnable() { // AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints());
public void run() {
AuctionHouseResourceDirectory rd = new AuctionHouseResourceDirectory( // ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
URI.create(RESOURCE_DIRECTORY) // executor.scheduleAtFixedRate(crawlerRunnable, 300, 300, TimeUnit.SECONDS);
); // }
AuctionHouseDiscovery.getInstance().addAuctionHouseDiscoveryInformation(rd.retrieveAuctionHouseEndpoints());
} // 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());
// }
// };
} }

View File

@ -2,9 +2,11 @@ package ch.unisg.tapas.auctionhouse.adapter.common.clients;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -18,25 +20,24 @@ import org.springframework.http.HttpStatus;
*/ */
public class WebSubSubscriber { 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()); Logger logger = Logger.getLogger(WebSubSubscriber.class.getName());
public void subscribeToAuctionHouseEndpoint(URI endpoint) { String AUCTION_HOUSE_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");
if (topic == null) { public WebSubSubscriber(String AUCTION_HOUSE_ENDPOINT) {
this.AUCTION_HOUSE_ENDPOINT = AUCTION_HOUSE_ENDPOINT;
}
public void subscribeToAuctionHouseEndpoint(URI endpoint) {
HashMap<String, String> links = discoverWebSubTopic(endpoint);
if (links.isEmpty()) {
return; return;
} }
subscribeToWebSub(topic); 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. // 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. // 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 // 2. Send a subscription request to the discovered WebSub hub to subscribe to events relevant
@ -52,23 +53,30 @@ public class WebSubSubscriber {
// - the implementation notes of the WebSub hub you are using to distribute events // - the implementation notes of the WebSub hub you are using to distribute events
} }
private String discoverWebSubTopic(String endpoint) { private HashMap<String, String> discoverWebSubTopic(URI endpoint) {
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder() HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint)) .uri(endpoint)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.GET() .GET()
.build(); .build();
HashMap<String, String> links = new HashMap<>();
try { try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == HttpStatus.OK.value()) { if (response.statusCode() == HttpStatus.OK.value()) {
// TODO decide with other groups about response structure and replace the hardcoded for (String link : response.headers().allValues("link")) {
// uri with response uri if (link.contains("rel=\"hub\"")) {
JSONObject jsonObject = new JSONObject(response.body()); String hub = link.split(">")[0];
System.out.println(jsonObject); links.put("hub", hub.substring(1));
return jsonObject.getString("topic"); } 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 { } else {
logger.log(Level.SEVERE, "Could not find a websub uri"); logger.log(Level.SEVERE, "Could not find a websub uri");
} }
@ -78,24 +86,26 @@ public class WebSubSubscriber {
} catch (IOException e) { } catch (IOException e) {
logger.log(Level.SEVERE, e.getLocalizedMessage(), 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(); HttpClient client = HttpClient.newHttpClient();
String body = new JSONObject() URI hubURI;
.put("hub.callback", AUCTION_HOUSE_ENDPOINT + "/auction-started") try {
.put("hub.mode", "subscribe") hubURI = new URI(hub);
.put("hub.topic", topic) } catch (URISyntaxException e) {
.put("hub.ws", false) // TODO Auto-generated catch block
.toString(); e.printStackTrace();
return;
}
HttpRequest request = HttpRequest.newBuilder() HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(WEBSUB_HUB_ENDPOINT)) .uri(hubURI)
.header("Content-Type", "application/json") .header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(body)) .POST(HttpRequest.BodyPublishers.ofString("hub.mode=subscribe&hub.callback=" + AUCTION_HOUSE_ENDPOINT +
"/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c" + "&hub.topic=" + topic))
.build(); .build();

View File

@ -3,12 +3,16 @@ package ch.unisg.tapas.auctionhouse.adapter.common.formats;
import ch.unisg.tapas.auctionhouse.domain.Auction; import ch.unisg.tapas.auctionhouse.domain.Auction;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.net.URI;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat; 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 * 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")); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
return mapper.writeValueAsString(representation); 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;
}
} }

View File

@ -1,20 +1,31 @@
package ch.unisg.tapas.auctionhouse.adapter.in.messaging.websub; 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.AuctionJsonRepresentation;
import ch.unisg.tapas.auctionhouse.adapter.common.formats.BidJsonRepresentation;
import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler; import ch.unisg.tapas.auctionhouse.application.handler.AuctionStartedHandler;
import ch.unisg.tapas.auctionhouse.application.port.in.AuctionStartedEvent; import ch.unisg.tapas.auctionhouse.application.port.in.AuctionStartedEvent;
import ch.unisg.tapas.auctionhouse.domain.Auction; import ch.unisg.tapas.auctionhouse.domain.Auction;
import ch.unisg.tapas.auctionhouse.domain.Bid;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionDeadline; import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionDeadline;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionHouseUri; import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionHouseUri;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionId; import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionId;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskType; import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskType;
import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskUri; import ch.unisg.tapas.auctionhouse.domain.Auction.AuctionedTaskUri;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; 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.Collection;
import java.util.Date;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -34,20 +45,89 @@ public class AuctionStartedEventListenerWebSubAdapter {
* @return 200 OK * @return 200 OK
* @throws URISyntaxException * @throws URISyntaxException
**/ **/
@PostMapping(path = "/auction-started") // TODO generate a new capability ID instead of using a hardcoded one.
public ResponseEntity<Void> handleExecutorAddedEvent(@RequestBody Collection<AuctionJsonRepresentation> payload) throws URISyntaxException { @PostMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c")
public ResponseEntity<Void> handleExecutorAddedEvent(@RequestBody String payload) throws URISyntaxException {
for (AuctionJsonRepresentation auction : payload) { System.out.println("new auctions :O");
auctionStartedHandler.handleAuctionStartedEvent( System.out.println(payload);
new AuctionStartedEvent(
new Auction(new AuctionId(auction.getAuctionId()),
new AuctionHouseUri(new URI(auction.getAuctionHouseUri())), JSONArray auctions = new JSONArray(payload);
new AuctionedTaskUri(new URI(auction.getTaskUri())), if (auctions.length() > 0) {
new AuctionedTaskType(auction.getTaskType()), JSONObject auction = auctions.getJSONObject(0);
new AuctionDeadline(auction.getDeadline())) 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); return new ResponseEntity<>(HttpStatus.OK);
} }
} }

View File

@ -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("${auction.house.uri}")
private String auctionHouseUri;
/**
* Controller to discover our websub topic
* @return 200 OK
**/
@GetMapping(path = "/websub/auctions")
public ResponseEntity<String> handleDiscoverWebSubAuction() {
HttpHeaders header = new HttpHeaders();
header.add("link", "<" + auctionHouseUri + "/auctions/>; rel=\"self\"");
header.add("link", "<" + webSubHubUri + ">; rel=\"hub\"");
return ResponseEntity.ok().headers(header).body("");
}
}

View File

@ -13,21 +13,9 @@ import org.springframework.web.bind.annotation.*;
@RestController @RestController
public class ValidateIntentWebSubAdapter { public class ValidateIntentWebSubAdapter {
@Value("${application.environment}") // TODO generate a new capability ID instead of using a hardcoded one.
private String environment; @GetMapping(path = "/auction-started/74c72c7f-2739-4124-aa35-a3225171a97c")
@GetMapping(path = "/auction-started")
public ResponseEntity<String> validateIntent(@RequestParam("hub.challenge") String challenge) { public ResponseEntity<String> 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);
} }
} }
}

View File

@ -15,7 +15,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
@Primary // @Primary
public class PublishAuctionStartedEventMqttAdapter implements AuctionStartedEventPort { public class PublishAuctionStartedEventMqttAdapter implements AuctionStartedEventPort {
private static final Logger LOGGER = LogManager.getLogger(PublishAuctionStartedEventMqttAdapter.class); private static final Logger LOGGER = LogManager.getLogger(PublishAuctionStartedEventMqttAdapter.class);

View File

@ -1,41 +1,27 @@
package ch.unisg.tapas.auctionhouse.adapter.out.messaging.websub; package ch.unisg.tapas.auctionhouse.adapter.out.messaging.websub;
import ch.unisg.tapas.auctionhouse.application.port.out.AuctionStartedEventPort; 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.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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; 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.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors;
/** /**
* This class is a template for publishing auction started events via WebSub. * This class is a template for publishing auction started events via WebSub.
*/ */
@Component @Component
@Primary
public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEventPort { public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEventPort {
// You can use this object to retrieve properties from application.properties, e.g. the @Value("${auction.house.uri}")
// WebSub hub publish endpoint, etc.
@Autowired
private ConfigProperties config;
@Value("${auctionhouse.uri}")
private String auctionHouseUri; private String auctionHouseUri;
@Value("${websub.hub.uri}") @Value("${websub.hub.uri}")
@ -47,21 +33,20 @@ public class PublishAuctionStartedEventWebSubAdapter implements AuctionStartedEv
public void publishAuctionStartedEvent(AuctionStartedEvent event) { public void publishAuctionStartedEvent(AuctionStartedEvent event) {
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
String body = new JSONObject() String body = "hub.url=" + auctionHouseUri + "/auctions/&hub.mode=publish";
.put("hub.url", auctionHouseUri + "/auctions")
.put("hub.mode", "publish")
.toString();
logger.info("Auctions updated:" + body);
HttpRequest request = HttpRequest.newBuilder() HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(webSubHubUri)) .uri(URI.create(webSubHubUri))
.header("Content-Type", "application/json") .header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(body)) .POST(HttpRequest.BodyPublishers.ofString(body))
.build(); .build();
try { try {
client.send(request, HttpResponse.BodyHandlers.ofString()); client.send(request, HttpResponse.BodyHandlers.ofString());
logger.info("WEBSUB send successfuly");
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.log(Level.SEVERE, e.getLocalizedMessage(), e); logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();

View File

@ -43,6 +43,7 @@ public class AuctionWonEventHttpAdapter implements AuctionWonEventPort {
.uri(auction.get().getTaskUri().getValue()) .uri(auction.get().getTaskUri().getValue())
.GET() .GET()
.build(); .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); var response = client.send(request, HttpResponse.BodyHandlers.ofString());
LOGGER.info(response.body()); LOGGER.info(response.body());
JSONObject responseBody = new JSONObject(response.body()); JSONObject responseBody = new JSONObject(response.body());

View File

@ -20,6 +20,9 @@ public class AuctionHouseDiscovery {
} }
}; };
// TODO load from config
// static String AUCTION_HOUSE_URI = "http://localhost:8086";
@Getter @Getter
private List<AuctionHouseDiscoveryInformation> auctionHouseDiscoveryList = new ArrayList<>() { private List<AuctionHouseDiscoveryInformation> auctionHouseDiscoveryList = new ArrayList<>() {
}; };
@ -29,7 +32,7 @@ public class AuctionHouseDiscovery {
// Add our information to list // Add our information to list
auctionHouseDiscoveryList.add(new AuctionHouseDiscoveryInformation( auctionHouseDiscoveryList.add(new AuctionHouseDiscoveryInformation(
new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI("http://localhost:8086")), new AuctionHouseDiscoveryInformation.AuctionHouseUri(new URI("http://localhost:8086")),
new AuctionHouseDiscoveryInformation.WebSubUri(new URI("http://localhost:8086/websub")), new AuctionHouseDiscoveryInformation.WebSubUri(new URI("http://localhost:8086/websub/auctions")),
new AuctionHouseDiscoveryInformation.TaskTypes(tasktypes), new AuctionHouseDiscoveryInformation.TaskTypes(tasktypes),
new AuctionHouseDiscoveryInformation.TimeStamp(new Timestamp(new Date().getTime())), new AuctionHouseDiscoveryInformation.TimeStamp(new Timestamp(new Date().getTime())),
new AuctionHouseDiscoveryInformation.GroupName("Group 1") new AuctionHouseDiscoveryInformation.GroupName("Group 1")

View File

@ -10,6 +10,8 @@ auction.house.uri=https://tapas-auction-house.86-119-35-40.nip.io
tasks.list.uri=http://localhost:8081 tasks.list.uri=http://localhost:8081
application.environment=development application.environment=development
auctionhouse.uri=http://localhost:8086 websub.hub.uri=https://pubsubhubbub.appspot.com
websub.hub.uri=http://localhost:3000 mqtt.broker.uri=tcp://broker.hivemq.com
mqtt.broker.uri=tcp://localhost:1883 # mqtt.broker.uri=tcp://localhost:1883
discovery.endpoint.uri=http://localhost:3500