Merge pull request #68 from SCS-ASSE-FS21-Group1/auction_house_external_communication
Implemented auctioning of tasks workflow in auction house
This commit is contained in:
commit
861cf82f67
|
@ -1,3 +1,3 @@
|
|||
server.port=8083
|
||||
|
||||
mqtt.broker.uri=tcp://localhost:1883
|
||||
mqtt.broker.uri=tcp://broker.hivemq.com:1883
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
* <a href="https://www.iana.org/assignments/media-types/">IANA</a> 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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<String> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String> 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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<BidReceivedEvent> {
|
||||
@NotNull
|
||||
public Bid bid;
|
||||
|
||||
public BidReceivedEvent(Bid bid){
|
||||
this.bid = bid;
|
||||
validateSelf();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package ch.unisg.tapas.auctionhouse.application.port.in;
|
||||
|
||||
public interface BidReceivedEventHandler {
|
||||
boolean handleNewBidReceivedEvent(BidReceivedEvent bidReceivedEvent);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user