Skip to content

Lab 9 - Send Order to the Kitchen

In this lab you'll complete the implementation of the HttpKitchenService to send the order to the Kitchen display remote service via a POST message.

A. Create a JavaBean for the POST Content

The Kitchen Display server API requires the following properties in an order:

  • kioskName (String): the name of the meal order kiosk sending the order
  • kioskId (Long): the ID for the meal order (this is the MealOrder's ID, not the order number)
  • items (List<String>): a list of strings for the menu items in the order

The JSON you'll be POSTing will look like this:

{
  "kioskName": "Ted",
  "kioskId": 125,
  "items": [
    "Burger: none",
    "Fries: large"
    ]
}
  1. Create a new JavaBean class
    • Name: SendOrderRequest
    • Package: com.welltestedlearning.mealkiosk.kitchen
  2. Add the 3 private fields (member variables) to match the property names from above.
  3. Generate the getters & setters for those 3 fields

B. Change The Displayable Interface

Make sure all tests pass before doing this refactoring.

Since the order request needs a list of strings to describe the order, we'll leverage the existing display() method that all MenuItems implement. However, the interface that they implement looks like this:

public interface Displayable {
  void display();
}

which doesn't return anything. We want to change this so the menu items return a formatted string that we use in the order request.

Let's change the interface so that display() returns a String instead of nothing (void):

  1. Open the Displayable interface file
  2. Use IntelliJ's refactoring tool to change the return value of the method:
    • Put the cursor on the display() method
    • Use the Refactor > Change Signature... menu tool
      • You can also use Command+F6 (Mac) or Ctrl+F6 (Windows)
    • Replace void in the Return Type box with String
    • Click on the Refactor button
  3. Build the project: Build > Build Project (or Command+F9 or Ctrl+F9)
  4. Fix each compile error, which is because the implementations of display() in Burger, Fries, etc., don't return a String (and therefore violate the interface contract). For example, instead of:
    System.out.println("Fries, size " + size);
    
    Replace it with:
    return "Fries: " + size;
    
  5. Continue to re-build the project and fix each compile error in the same way, replacing the System.out.println with returning a String.

Let's now fix the MealOrder's display method, which relied on the item to display itself (which it no longer does).

  1. Open up MealOrder
  2. Go to the display() method
  3. Inside the for loop, replace item.display(); with System.out.println(item.display());

C. Ensure Correct Formatting of Menu Items

So that the Kitchen Display can properly show the order items, you need to send the description of each order item in a particular way.

Burger Items

Since burgers can have a variety of (or no) toppings, we'll test its display method more deeply.

  1. Open up the BurgerTest class and add the following test methods:
    @Test
    public void plainBurgerDisplaysCorrectly() throws Exception {
      Burger plainBurger = new Burger();
      assertThat(plainBurger.display())
          .isEqualTo("Burger: none");
    }
    
    @Test
    public void burgerWithCheeseDisplaysCorrectly() throws Exception {
      Burger cheeseBurger = new Burger(BurgerTopping.CHEESE);
      assertThat(cheeseBurger.display())
          .isEqualTo("Burger: cheese");
    }
    
    @Test
    public void burgerWithCheeseAndBaconDisplaysCorrectly() throws Exception {
      Toppings toppings = new Toppings();
      toppings.addTopping(BurgerTopping.CHEESE);
      toppings.addTopping(BurgerTopping.BACON);
      Burger baconCheeseBurger = new Burger(toppings);
    
      assertThat(baconCheeseBurger.display())
          .isEqualTo("Burger: cheese, bacon");
    }
    
  2. Run all of the tests in BurgerTest. Fix any failing tests by changing the code to make them pass.

Other Menu Items

We'll test the display formatting of the other menu items with a different kind of test.

  1. Create a test class
    • Name: SendOrderRequestTest
    • Package: com.welltestedlearning.mealkiosk.kitchen
  2. Copy this code into the new test class:
    package com.welltestedlearning.mealkiosk.kitchen;
    
    import com.welltestedlearning.mealkiosk.domain.Burger;
    import com.welltestedlearning.mealkiosk.domain.BurgerTopping;
    import com.welltestedlearning.mealkiosk.domain.Drink;
    import com.welltestedlearning.mealkiosk.domain.Fries;
    import com.welltestedlearning.mealkiosk.domain.MenuItem;
    import org.junit.Test;
    
    import java.util.Arrays;
    import java.util.List;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    public class SendOrderRequestTest {
      @Test
      public void menuItemsTransformedToListOfStrings() throws Exception {
        List<MenuItem> menuItems =
            Arrays.asList(new Drink(Drink.DRINK_LARGE),
                          new Fries(Fries.LARGE),
                          new Burger(BurgerTopping.AVOCADO));
    
        List<String> strings = SendOrderRequest.toDisplayStrings(menuItems);
    
        assertThat(strings)
            .hasSize(3)
            .containsExactlyInAnyOrder(
                "Drink: large",
                "Fries: large",
                "Burger: avocado");
      }
    }
    
  3. Implement the static toDisplayStrings method in SendOrderRequest to make the test pass.
  4. Add the following constant at the top of SendOrderRequest:
    private static final String KIOSK_NAME = "TED";
    
    but replace "TED" with a name of your choosing (this will identify your kiosk's orders).
  5. Once it passes (and all tests continue to pass), copy this method into the SendOrderRequest class:
      public static SendOrderRequest from(MealOrder mealOrder) {
        SendOrderRequest sendOrderRequest = new SendOrderRequest();
        sendOrderRequest.setKioskId(mealOrder.getId());
        sendOrderRequest.setKioskName(KIOSK_NAME);
        sendOrderRequest.setItems(toDisplayStrings(mealOrder.menuItems()));
        return sendOrderRequest;
      }
    

D. Create Kitchen Response JavaBean

When we send the order to the Kitchen Display service, it'll send back a response as JSON that looks like this:

{
    "orderNumber": 5,
    "kioskId": 129
}
  1. Create a new class that can store the above two properties (note that both are Longs):
  2. Name: CreatedOrderResponse
  3. Package: com.welltestedlearning.mealkiosk.kitchen
  4. Don't forget to generate the getters & setters

E. Send the Request to the Kitchen Via POST

Now that we have all the classes we need to create the request and get a response, let's send it to the Kitchen Display service.

  1. Open the HttpKitchenService
  2. Replace the sendOrder method with the following:
    @Override
    public Long sendOrder(MealOrder mealOrder) {
      // * Transform the MealOrder to a SendOrderRequest object
      //   Use the static .from() method on SendOrderRequest
      // * Name the variable orderRequest
      // * This will execute the POST operation:
      CreatedOrderResponse response = restTemplate.postForObject(
          KITCHEN_POST_URL, orderRequest, CreatedOrderResponse.class);
      // * Extract the orderNumber from the response
      // * Return the orderNumber
    }
    
  3. Implement this method as per the comments.

Try It Out and Watch The Kitchen Display

If everything is working properly, POSTs to your Meal Kiosk API will cause the order to appear on the Kitchen Display.