Skip to content

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 order
  • kioskId (Long): the ID for the coffee order (this is the CoffeeOrder'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"
    ]
}
  1. Create a new DTO class named SendOrderRequest
  2. Add 3 private fields (member variables) to match the property names from above.
    • kioskName as a String
    • kioskId as a Long
    • items as a List<String>
  3. 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:

  1. 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).

  1. 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 (a long)
  • kioskId is a long the ID of the CoffeeOrder 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 longs.


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.

  1. Create a new class, named HttpSendOrderCoffeeService, that implements the SendOrderCoffeeService 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!";
      }
    
  2. Annotate this implementation with @Service.

  3. 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;
    
  4. These @Value() annotations tell Spring to read these values from configuration, so add the following two lines to your application.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}
    
  5. 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 the StubSendOrderCoffeeService class
    • Add @Profile("prod") as an annotation for the HttpSendOrderCoffeeService class
    • In the application.properties file, add a new line: spring.profiles.active=dev
  6. 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.

  7. Open up the application.properties file and change the active profile from dev to prod. If you try sending an order now, you should see the status be Hi 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.

  1. 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
    }
    
  2. Implement this method as per the comments.

  3. 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.

  1. 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
    }
    
  2. 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 the orderNumber is the Template Variable that you'll be replacing.
  3. Try viewing an order that's been sent and you should see the status come back from the remote server.

  4. If you refresh the order view page, you should see the status change.