Lab17 send order real
Now you'll implement the real send-order service that will talk to the remote system.
A. Create a DTO for the POST Content¶
The Coffee Display server API requires the following properties to be sent for an order:
kioskName
(String
): the name of the kiosk sending the orderkioskId
(Long
): the ID for the coffee order (this is theCoffeeOrder
's ID)items
(List<String>
): a list of strings for the items in the order
The JSON you'll be POSTing will look like this:
{
"kioskName": "Ted",
"kioskId": 8,
"items": [
"Size: MEDIUM",
"Creamer: MILK",
"Sweetener: NONE"
]
}
- Create a new DTO class named
SendOrderRequest
- Add 3 private fields (member variables) to match the property names from above.
kioskName
as aString
kioskId
as aLong
items
as aList<String>
- Generate the getters & setters for those 3 fields
B. Create Converter to DTO¶
To make it easier to create the above DTO from a coffee order, you'll create a factory method.
In the SendOrderRequest
:
-
Add the following constant at the top:
private static final String KIOSK_NAME = "TED";
but replace "TED"
with a name of your choosing (this will identify your kiosk's orders).
- Add this method into the
SendOrderRequest
class:public static SendOrderRequest from(CoffeeOrder coffeeOrder) { SendOrderRequest sendOrderRequest = new SendOrderRequest(); sendOrderRequest.setKioskId(coffeeOrder.getId()); sendOrderRequest.setKioskName(KIOSK_NAME); // // convert the coffee order's `CoffeeItem`s to a `List<String>` here // List<String> coffeeItems = ... // sendOrderRequest.setItems(coffeeItems); return sendOrderRequest; }
C. Create Display Response DTO¶
When you send the order to the Display service, it'll send back a response as JSON that looks like this:
{
"orderNumber": 9,
"kioskId": 1
}
Where:
orderNumber
is the remote system's identifier (along
)kioskId
is along
the ID of theCoffeeOrder
that you sent (i.e., the one you might use to look up the order in the repository).
Create a new DTO that represents this JSON, named SentOrderResponse
and add two member variables, with getters & setters, that match the property names.
Remember that both are long
s.
D. Create Empty HTTP Service¶
Now you'll creating an HTTP implementation of the service, where you'll use a RestTemplate
to send the request to the remote service.
-
Create a new class, named
HttpSendOrderCoffeeService
, that implements theSendOrderCoffeeService
interface. For now put in empty implementations for the two methods:@Override public long send(CoffeeOrder coffeeOrder) { return -1; } @Override public String statusFor(Long orderNumber) { return "Hi From Production!"; }
-
Annotate this implementation with
@Service
. -
Add the following member variables to the class:
private final RestTemplate restTemplate = new RestTemplate(); @Value("${order.post.uri}") private String postOrderUri; @Value("${order.get.uri}") private String getStatusUri;
-
These
@Value()
annotations tell Spring to read these values from configuration, so add the following two lines to yourapplication.properties
file:order.post.uri=http://coffee-order-display.herokuapp.com/api/orders order.get.uri=http://coffee-order-display.herokuapp.com/api/orders/{orderNumber}
-
Since you'll now have two services implementating the same interface, you'll need to use the Spring Profile feature to select among the implementations:
- Add
@Profile("dev")
as an annotation for theStubSendOrderCoffeeService
class - Add
@Profile("prod")
as an annotation for theHttpSendOrderCoffeeService
class - In the
application.properties
file, add a new line:spring.profiles.active=dev
- Add
-
Try out the application and it should still work as it did before, since the profile is set to
dev
, Spring will use the Stub implementation. -
Open up the
application.properties
file and change the active profile fromdev
toprod
. If you try sending an order now, you should see the status beHi From Production!
since Spring should now be using the HTTP implementation.
E. Send the Request to the Kitchen Via POST¶
Now you'll implement the send order in the HttpSendOrderCoffeeService
class.
-
Replace the
send
method with the following:@Override public long send(CoffeeOrder coffeeOrder) { // * Transform the CoffeeOrder to a SendOrderRequest object // Use the static .from() method on SendOrderRequest that you wrote before // * Name the variable orderRequest // * This will execute the POST operation: SentOrderResponse response = restTemplate.postForObject( postOrderUri, orderRequest, SentOrderResponse.class); // * Extract the orderNumber from the response // * Return the orderNumber }
-
Implement this method as per the comments.
-
Try sending an order and if everything is working, your order will appear on the Coffee Order Display.
F. Create DTO For Status Response¶
To find out the status for an order, you'll be doing a GET to the remote system, which will returns JSON that looks something like this:
{
"orderNumber": 1,
"kioskId": 123,
"status": "COMPLETED"
}
Create a DTO that matches those properties in a new class called OrderStatusResponse
.
Note that both the orderNumber
and kioskId
are long
values, and the status
is a String
.
Remember to use IntelliJ to generate the getters & setters.
G. Fetch the Status from the Kitchen¶
In the HttpSendOrderCoffeeService
, you'll implement the fetching of the order status.
-
Replace the
statusFor
method with the following:@Override public String statusFor(Long orderNumber) { // Create a Map to associate the template variable named "orderNumber" with the actual order number // use the RestTemplate to make the request to the URL for the given orderNumber // You'll use the OrderStatusResponse class that you created above // extract the Status from the response // return the status }
-
Implement this method as per the comments. Note that this will be very similar to the currency conversion service HTTP implementation.
- Remember that the URI here looks like this:
http://coffee-order-display.herokuapp.com/api/orders/{orderNumber}
, so here theorderNumber
is the Template Variable that you'll be replacing.
- Remember that the URI here looks like this:
-
Try viewing an order that's been sent and you should see the status come back from the remote server.
-
If you refresh the order view page, you should see the status change.