Putting things together

You now have all the required knowledge to define HTTP endpoints for the list, create, and get entry points of the Shop service so that your HTTP endpoints can read both HTML form data and JSON data, and can return either HTML or JSON content according to the client's preferences.

For instance, here is the code for how the create endpoint can look like:

  val create = Action { implicit request =>
    createItemFormModel.bindFromRequest().fold(
      formWithErrors => render {
        case Accepts.Html() =>
          BadRequest(views.html.createForm(formWithErrors))
        case Accepts.Json() => BadRequest(formWithErrors.errorsAsJson)
      },
      createItem => {
        shop.create(createItem.name, createItem.price) match {
          case Some(item) => render {
            case Accepts.Html() => Redirect(routes.Items.details(item.id))
            case Accepts.Json() => Ok(Json.toJson(item))
          }
          case None => InternalServerError
        }
      }
    )
  }

The Java equivalent code is as follows:

public static Result create() {
  Form<CreateItem> submission = Form.form(CreateItem.class).bindFromRequest();
  if (submission.hasErrors()) {
    return render(
      version(MimeTypes.HTML, () ->
        badRequest(views.html.createForm.render(submission))),
      version(MimeTypes.JSON, () -> badRequest(submission.errorsAsJson()))
    );
  } else {
    CreateItem createItem = submission.get();
    Item item = shop.create(createItem.name, createItem.price);
    if (item != null) {
      return render(
        version(MimeTypes.HTML, () ->
          redirect(routes.Items.details(item.id))),
        version(MimeTypes.JSON, () -> ok(Json.toJson(item)))
      );
    } else {
      return internalServerError();
    }
  }
}

Note that when the action returns a 500 status (Internal Server Error), it does not differentiate between JSON or HTML clients because the response has no content. It would be better to return a pretty HTML page to HTML clients.

Also, note that you have to update your tests for the HTTP layer to explicitly tell that you prefer getting JSON instead of HTML. Just add the corresponding header in your HTTP requests:

FakeRequest(routes.Items.list()).withHeaders(ACCEPT -> MimeTypes.JSON)

The Java equivalent code is as follows:

fakeRequest(routes.Items.list()).withHeader(ACCEPT, MimeTypes.JSON);

The remaining entry points of the Shop service are update and delete. They are mapped to actions using the put and delete verbs; however, performing this kind of requests is not possible from HTML forms, so the recommended way consists of using some JavaScript code, executed on the client side, to send HTTP requests using put and delete. This approach is covered in the next chapter. Alternatively, you can also change your route definitions to use post instead of put and delete (note that in this case, you will also have to use different URL patterns for these routes so that they don't clash with the create route).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.136.119