Skip to content
This repository has been archived by the owner on Apr 13, 2019. It is now read-only.

library create

Konstantin Sobolev edited this page May 3, 2017 · 7 revisions

Create operation

Lets add an operation for adding new books. It will take a list of book records as an input and return a list of created book IDs (or errors).

Schema

Operation schema is is shown below. There are two notable things:

  • input and output types differ from the resource type, it's not a map[BookId, BookRecord] now but a list[BookRecord] for input and list[BookId] for output.
  • input projection marks everything as required (+), framework will guarantee fields presence and will reject any calls with missing data
  create {
    inputType list[BookRecord]
    inputProjection *(
      +title,       // title required
      +author:+id,  // author id required (and this author must be present!)
      +text:+plain  // text required
    )

    outputType list[BookId]
  }

Operation implementation

Operation implementation is very simple. We extract all fields from the incoming BookRecord instance, lookup author by ID and ask backend to add a new book. Input fields are guaranteed to be non-null since they are marked as required.

public class BooksCreateOperation extends AbstractCreateOperation {

  BooksCreateOperation(@NotNull CreateOperationDeclaration declaration) {
    super(declaration);
  }

  @Override
  protected @NotNull CompletableFuture<BookId_List.Data> process(
      @NotNull BookId_List.Builder.Data responseBuilder,
      @NotNull BookRecord_List inputData,
      @Nullable InputBooksFieldProjection inputProjection,
      @NotNull OutputBooksFieldProjection outputProjection
  ) {

    BookId_List.Builder bookIdList = BookId_List.create();
    responseBuilder.set(bookIdList);

    for (BookRecord book : inputData.datums()) {
      String title = book.getTitle();
      assert title != null; // guaranteed by input projection

      Text text = book.getText();
      assert text != null;
      PlainText plainText = text.getPlain();
      assert plainText != null;

      Author author = book.getAuthor();
      assert author != null;

      AuthorId authorId = author.getId();
      assert authorId != null;

      AuthorsBackend.AuthorData authorData = AuthorsBackend.get(authorId);
      if (authorData == null) {
        bookIdList.addError(new ErrorValue(
            HttpStatusCode.BAD_REQUEST, 
            "Author with id " + authorId.getVal() + " not found"
        ));
      } else {
        BookId bookId = BooksBackend.addBook(title, authorId, plainText.getVal());
        bookIdList.add(bookId);
      }
    }

    return CompletableFuture.completedFuture(responseBuilder);
  }
}

Plug it into BooksResourceFactory and we're done:

  @Override
  protected @NotNull CreateOperation<BookId_List.Data> constructCreateOperation(
    @NotNull CreateOperationDeclaration operationDeclaration
  ) throws ServiceInitializationException {
    return new BooksCreateOperation(operationDeclaration);
  }

Running

Adding a new book:

curl -s -g -X POST -d '[{"title":"Test","author":1,"text":"sample text"}]' "http://localhost:8888/books"
[4]

This created book with id 4:

curl -s -g "http://localhost:8888/books/4(title,author:(id,record(firstName,lastName)),text:plain)"
{"title":"Test","author":{"id":1,"record":{"firstName":"Allan","lastName":"Poe"}},"text":"sample text"}

Framework ensures that requred data is present. Lets skip text for example:

curl -s -g -X POST -d '[{"title":"Test","author":1}]' "http://localhost:8888/books"
Error reading create request body: Required field 'text' is missing at line 1 column 29

Next section: adding update operation